/* base.css — structure tokens. no color lives here. (skin owns color.)
   build phase: lean. full folio header at ship.
   tokens = law. change here, everything updates. */

:root {
  /* spacing — the invisible grid (alignment + placement) */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 40px;

  /* type — large print is the baseline, not a setting (pharma grade).
     (Sum 2026-07-13) T-SHIRT SCALE — tokenize every font to one of these. XL is the workhorse (everything the user
     reads/clicks); HUGE is the rare shout (titles). We basically never use HUGE in this app — reach for XL. */
  --fs-xl:     20px;   /* the standard big-print size — the floor for any text the user READS or CLICKS */
  --fs-huge:   28px;   /* only when something truly needs to shout (titles) — rarely */
  --fs-chrome: 18px;
  --fs-label:  var(--fs-xl);
  --fs-body:   var(--fs-xl);   /* (Sum 2026-07-13) was 28px (huge) — that "huge" was leaking into the linter + suggestor; body text is XL */
  --fs-title:  var(--fs-huge);
  --fs-ui:     var(--fs-xl);

  /* radii */
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 16px;

  /* hit targets — palsy rule: never below 30px. topbar runs roomier. */
  --hit: 44px;
  --topbar-h: 56px;

  /* topbar tiles — ONE tile size. every launcher (nav · deck · suite) is --hit square,
     its icon --tb-icon. change here → every tile in the bar updates. (2026-07-09) */
  --tb-icon:     30px;   /* the rendered PNG / css icon inside a tile */
  --tb-emoji-fs: 26px;   /* the emoji-icon glyph size (matches the PNG optical weight) */
  --tb-icon-sub: 26px;   /* the same, one notch down, for the subbar drawer pills */

  --font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; overflow: hidden; }   /* page never scrolls. cards do. */

/* the zoom STAGE — holds the whole app (topbar · subbar · desk). EAT ME/DRINK ME scales THIS with a
   transform (zoom.js), NOT body.zoom — CSS zoom on an ancestor mis-sizes descendant iframes, letterboxing
   preview/ban/monaco in white. transform scales them as one layer, so they fill at any zoom. zoom.js sets
   width/height to 100/z so scaling by z lands the stage exactly on the viewport. */
#zoom-root { display: flex; flex-direction: column; width: 100vw; height: 100vh; overflow: hidden; transform-origin: 0 0; flex-shrink: 0; }   /* flex-shrink:0 — as a body flex-child, a 100/z-vh stage (z<1) must NOT shrink back to 100vh, or scale(z) renders it short → gap at the bottom */

body {
  display: flex;
  flex-direction: column;
  font-family: var(--font);
  font-size: var(--fs-body);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

/* ── bevel — repetition: one definition, used everywhere. ───────────
   the offsets are structure (here). the colors are skin (there). */

.bevel {
  box-shadow:
    inset 1px 1px 0 var(--bevel-light),
    inset -1px -1px 0 var(--bevel-dark);
}

/* ── btn — physical object, has mass. can you pick it up? ───────────── */

.btn {
  background: var(--btn);
  color: var(--text);
  border: none;
  border-radius: var(--r-md);
  box-shadow: 0 3px 0 var(--btn-sh);
  min-height: var(--hit);
  font: inherit;
  cursor: pointer;
}

.btn:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--btn-sh); }

/* ── ♿ the a11y layer (ACCESSIBILITY.md pass 1+6, 2026-07-14) — tokens + three global rules ── */

/* the focus ring — one ring, everywhere, only for keyboard/switch travel (:focus-visible skips mouse
   clicks). high-contrast teal on the dark skins; the outline sits OUTSIDE so it never squeezes layout. */
:focus-visible {
  outline: 3px solid var(--focus-ring, #57e0c8);
  outline-offset: 2px;
  border-radius: 4px;
}

/* the skip link — invisible until a keyboard lands on it, then a clear banner to jump the chrome */
.skip-link {
  position: fixed; top: -100px; left: 12px; z-index: 99999;
  padding: 10px 18px; border-radius: var(--r-md);
  background: var(--focus-ring, #57e0c8); color: #08211c;
  font-size: var(--fs-ui); font-weight: 700; text-decoration: none;
  transition: top .12s;
}
.skip-link:focus { top: 12px; }

/* reduced motion — the OS setting wins: curb every animation/transition (no flashing, no loops).
   near-zero (not zero) so animationend/transitionend events still fire and JS state machines finish. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ⌨ FOCUS MODE (Sum 2026-07-14) — keyboard travel made VISIBLE. body.kbd-mode set by OZ_KBD (a11y.js). */
body.kbd-mode :focus {
  outline: 3px solid var(--focus-ring, #57e0c8) !important;
  outline-offset: 2px;
}
/* the pop-out flash — Esc lands you HERE: a dashed ring on the surface you popped to, 1.6s */
.a11y-popped {
  outline: 3px dashed var(--focus-ring, #57e0c8) !important;
  outline-offset: 3px;
}
/* the ⌨ topbar toggle, lit while focus mode is on */
.tb-kbd.lit {
  background: rgba(87, 224, 200, .22);
  box-shadow: inset 0 0 0 2px var(--focus-ring, #57e0c8);
  border-radius: 8px;
}

/* ⌖ focus mode — cartography's "you are here" (Sum: the dashed circle was just noise). big + bold;
   ON wears the same collar-red .active as deck/drawer (topbar.css), glyph warms to match. */
.tb-youarehere { font-size: 30px; line-height: 1; font-weight: 700; }
.tb-kbd.active .tb-youarehere { color: var(--accent, #d33); text-shadow: 0 0 8px var(--accent, #d33); }

/* ⌨ a KBD-GRABBED card/bot visibly lifts off the desk (hold G on its head · arrows dock · release) */
.card.kbd-grab, .agent-bar.kbd-grab {
  outline: 3px solid var(--focus-ring, #57e0c8);
  outline-offset: 2px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .55);
}

/* ▮ CHUNKY MODE (Sum 2026-07-14) — fatter TARGETS, same layout scale. tokens are law: bump --hit +
   the grabbable chrome. zoom (eat/drink me) scales the world; chunky just makes it easier to HIT. */
body.chunky { --hit: 60px; }
body.chunky .tb-btn { min-width: 52px; min-height: 48px; }
body.chunky .mc-pit-btn { min-width: 48px; min-height: 44px; }
body.chunky .mc-wing-grip-h { height: 34px; }
body.chunky .mc-wing-grip-v { width: 34px; }
body.chunky .mc-tool-split:not(.wide) > .mc-split, body.chunky .mc-fix:not(.wide) .mc-fix-body > .mc-split, body.chunky .mc-sq-main:not(.wide) > .mc-split { height: 34px; }
body.chunky .mc-tool-split.wide > .mc-split, body.chunky .mc-fix.wide .mc-fix-body > .mc-split, body.chunky .mc-sq-main.wide > .mc-split { width: 34px; }
.tb-chunky-glyph { font-size: 26px; line-height: 1; }

/* ? THE KEY MAP — big type, one card, the whole travel language */
#oz-keymap { position: fixed; inset: 0; z-index: 100000; background: rgba(8, 10, 14, .72); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.oz-keymap-box { background: #16181d; color: #eef1f5; border: 2px solid var(--focus-ring, #57e0c8); border-radius: 14px; padding: 26px 34px; max-width: 560px; font-size: var(--fs-ui, 20px); line-height: 1.5; box-shadow: 0 18px 50px rgba(0,0,0,.6); }
.oz-keymap-box h2 { margin: 0 0 12px; font-size: 26px; color: var(--focus-ring, #57e0c8); }
.oz-keymap-box dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 18px; margin: 0; }
.oz-keymap-box dt { font-weight: 800; color: var(--focus-ring, #57e0c8); white-space: nowrap; }
.oz-keymap-box dd { margin: 0; }
.oz-keymap-box p { margin: 14px 0 0; opacity: 1; color: #9aa3ad; font-size: 16px; }

/* 🚪 THE PER-BODY DOOR (onboard.js) — big type, big toggles; itself accessible (it must be) */
#oz-onboard { position: fixed; inset: 0; z-index: 100001; background: rgba(8, 10, 14, .78); display: flex; align-items: center; justify-content: center; }
.oz-ob-box { background: #16181d; color: #eef1f5; border: 2px solid var(--focus-ring, #57e0c8); border-radius: 16px; padding: 30px 36px; max-width: 620px; width: min(92vw, 620px); box-shadow: 0 20px 60px rgba(0,0,0,.65); }
.oz-ob-box h2 { margin: 0 0 8px; font-size: 30px; }
.oz-ob-box p { margin: 0 0 18px; font-size: 18px; color: #b9c1ca; line-height: 1.45; }
.oz-ob-rows { display: flex; flex-direction: column; gap: 10px; }
.oz-ob-row { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; text-align: left; background: #23262d; color: #eef1f5; border: 2px solid #3a3f47; border-radius: 12px; padding: 12px 18px; min-height: var(--hit, 44px); cursor: pointer; font: inherit; }
.oz-ob-row:hover { border-color: #5a626c; }
.oz-ob-row.on { background: #0e3a33; border-color: var(--focus-ring, #57e0c8); box-shadow: inset 0 0 0 1px var(--focus-ring, #57e0c8); }
.oz-ob-big { font-size: 22px; font-weight: 800; }
.oz-ob-small { font-size: 16px; color: #aeb7c0; }
.oz-ob-row.on .oz-ob-small { color: #cde8e2; }
.oz-ob-done { margin-top: 18px; width: 100%; min-height: 54px; font-size: 22px; font-weight: 800; background: #1d7a3e; color: #fff; border: 0; border-radius: 12px; box-shadow: 0 4px 0 #14582c; cursor: pointer; }
.oz-ob-done:active { transform: translateY(2px); box-shadow: 0 2px 0 #14582c; }

/* airy letters — the dyslexia-friendly spacing mode (letterforms breathe; big type is already law) */
body.dyslexia-air { letter-spacing: .035em; word-spacing: .1em; }
body.dyslexia-air p, body.dyslexia-air .mc-tool-msg, body.dyslexia-air .msg { line-height: 1.7; }

/* PEAK SAAS — the last row: a washing-machine GLYPH + a dial-on-NORMAL GLYPH (CSS-drawn, monochrome,
   currentColor), then "Peak SaaS Skin" set in ACTUAL fine print. the row is the joke. */
.oz-ob-box { max-height: 88vh; overflow-y: auto; }
.oz-ob-saas { flex-direction: row; align-items: center; gap: 12px; }
.oz-ob-saas-glyphs { display: inline-flex; gap: 8px; align-items: center; }
.ob-washer { display: inline-block; width: 22px; height: 26px; border: 2px solid currentColor; border-radius: 5px; position: relative; }
.ob-washer::before { content: ''; position: absolute; top: 2px; left: 2px; right: 2px; height: 3px; border: 1px solid currentColor; border-radius: 1px; }   /* the control panel strip */
.ob-washer::after { content: ''; position: absolute; top: 8px; left: 3px; right: 3px; bottom: 3px; border: 2px solid currentColor; border-radius: 50%; }   /* the porthole door */
.ob-dial-wrap { display: inline-flex; flex-direction: column; align-items: center; gap: 1px; }
.ob-dial-lbl { font-size: 13px; font-weight: 800; letter-spacing: .06em; line-height: 1; }
.ob-dial { display: inline-block; width: 18px; height: 18px; border: 2px solid currentColor; border-radius: 50%; position: relative; }
.ob-dial::after { content: ''; position: absolute; top: 1px; left: 50%; width: 2px; height: 6px; margin-left: -1px; background: currentColor; }
.oz-ob-fineprint { font-size: 13px; letter-spacing: .02em; color: #9aa3ad; }
.oz-ob-saas.on .oz-ob-fineprint { color: #cde8e2; }

/* 🔤 the glyph CHIP — what a png button wears on the clean skins: its glyph twin or its own name */
.gl-chip { display: inline-flex; align-items: center; justify-content: center; font-size: 17px; font-weight: 700; line-height: 1; min-width: 20px; padding: 1px 3px; letter-spacing: .01em; }
button .gl-chip, a .gl-chip { pointer-events: none; }

/* 🖼 an emoji's PNG twin, swapped in-place by the icon bean (fantasy skins) — sits like a character */
.em-ico { height: 1.2em; width: auto; vertical-align: -0.2em; display: inline-block; }

/* the DRAWN bubbles (clean tier) — speech = pointed tail, thought = dot trail; currentColor line art */
.gl-drawn { display: inline-block; position: relative; vertical-align: -0.08em; }
.gl-speech { width: 0.95em; height: 0.72em; border: 0.11em solid currentColor; border-radius: 0.3em; }
.gl-speech::after { content: ''; position: absolute; left: 0.1em; bottom: -0.32em; border: 0.14em solid transparent; border-top-color: currentColor; }
.gl-think { width: 0.95em; height: 0.72em; border: 0.11em solid currentColor; border-radius: 50%; }
.gl-think::after { content: ''; position: absolute; left: -0.02em; bottom: -0.34em; width: 0.14em; height: 0.14em; border-radius: 50%; background: currentColor; box-shadow: 0.2em 0.14em 0 -0.02em currentColor; }
