/* ==========================================================================
   game-console-ui-theme / tokens
   --------------------------------------------------------------------------
   This file is the single source of truth. Every literal value in the theme
   lives here exactly once. The Tailwind adapters next to it (theme.css for
   v4, preset.js for v3) hold no values of their own; they point at these
   custom properties with var().

   Each group is annotated with the creative-direction axis the choice
   serves. The four axes are tone register, aesthetic philosophy, audience
   relationship, and sensory ambition. Read them at
   https://rampstack.co/framework/creative-direction

   This theme is a shell: the tokens describe both a visual register (a dark
   dashboard built for a screen across a room) and the geometry of that
   dashboard, which shell/shell.css draws with them. The SHELL GEOMETRY
   group near the bottom is the part a register theme would not have.

   WHY EVERYTHING IS BIGGER THAN YOU EXPECT. This register is designed for a
   ten-foot viewing distance: a screen on a wall, read from a couch, driven
   without a pointer. The rule of thumb the broadcast world settled on is
   that type read from ten feet needs roughly three times the size it needs
   at arm's length, so the body size here is 20px and the floor is 15px.
   Nothing in this file is sized for a desk.

   Contrast ratios in the comments are WCAG 2.1 relative-luminance figures,
   computed from these exact hex values and quoted against the surface
   named. The ground is dark and the ink is light, so every ratio below is a
   light-on-dark reading. Every text pairing here clears AA; most clear AAA.
   ========================================================================== */

:root {
  /* ----------------------------------------------------------------------
     GROUND AND SCENE
     Aesthetic philosophy axis. The ground is dark by default and that is a
     functional decision before it is a stylistic one: a bright field at
     ten feet in a dim room is a lamp pointed at the reader, and every
     dashboard built for a television has landed in the same place for the
     same reason. The scene color is the ground's texture and the base tone
     of the wallpaper layer; it sits 1.11:1 from the ground on purpose.
     It is texture, not information, and nothing may depend on seeing it.
     ---------------------------------------------------------------------- */
  --tv-ground: #101216;        /* the dashboard field */
  --tv-scene: #191d23;         /* wallpaper base tone, 1.11:1, decorative only */

  /* ----------------------------------------------------------------------
     SURFACES
     Aesthetic philosophy axis. A tile face sits one quiet step above the
     ground (1.16:1) and the raised surface one step above that (1.27:1).
     Both steps are deliberately small. On this shell the focus ring is the
     loudest object on screen by design, so the resting state of a tile has
     to stay quiet enough that the ring wins without competition. Chrome is
     DARKER than the ground rather than lighter: the hint bar is a base the
     dashboard stands on, and a bright strip at the bottom of a dark screen
     reads as a second focus.
     ---------------------------------------------------------------------- */
  --tv-surface: #1c2128;        /* tile face, panel */
  --tv-surface-raised: #2b333d; /* focused tile face, hovered rows, code blocks */
  --tv-chrome: #0b0d10;         /* the hint bar */

  /* ----------------------------------------------------------------------
     INK
     Audience relationship axis. Slightly cool near-white rather than pure
     white: at this size and this distance, full white on near-black buzzes
     at the edges. Muted ink is quoted against its worst surface because
     secondary text appears on all of them.
       ink on chrome 17.96:1, on ground 17.31:1, on scene 15.62:1,
       on surface 14.94:1, on surface-raised 11.79:1
       ink-muted on chrome 9.07:1, on ground 8.74:1, on scene 7.89:1,
       on surface 7.54:1, on surface-raised 5.96:1
     ---------------------------------------------------------------------- */
  --tv-ink: #f4f6f8;
  --tv-ink-muted: #a9b2bd;

  /* ----------------------------------------------------------------------
     THE ACCENT
     Sensory ambition axis. Exactly one accent, a warm amber, and it is
     spent almost entirely on one job: the focus ring. That is the whole
     colour argument of this shell. A dashboard driven without a pointer
     has to answer "where am I" from across a room before it answers
     anything else, so the accent is not distributed across the interface
     as decoration; it is saved for the one mark that says where you are,
     plus the primary button, which is the same question asked in a view.
       accent on chrome 10.78:1, on ground 10.39:1, on scene 9.37:1,
       on surface 8.97:1, on surface-raised 7.08:1
       accent-ink on accent 10.34:1
     Every one of those clears the 3:1 non-text UI floor several times over,
     which is what lets the ring be read as a shape and not just a tint.
     ---------------------------------------------------------------------- */
  --tv-accent: #f4b64a;
  --tv-accent-ink: #16120a;

  /* ----------------------------------------------------------------------
     DESTRUCTIVE
     Tone register axis. One red, for the action that deletes something and
     for invalid input, nothing else. Backing out of a view is not
     destructive and the back control does not use it: on a shell where
     going back is the most common thing a reader does, painting it as a
     hazard teaches the wrong reflex.
       destructive on surface 5.88:1, on ground 6.81:1
       destructive-ink on destructive 6.89:1
     ---------------------------------------------------------------------- */
  --tv-destructive: #f2776b;
  --tv-destructive-ink: #1a0d0b;

  /* ----------------------------------------------------------------------
     FLAT SEMANTIC FILLS
     Aesthetic philosophy axis. The inversion of the light-register
     convention: on a dark ground the badge fills are DEEP versions of each
     hue and the text on them is full-strength light ink, so meaning lives
     in the hue and legibility never depends on it. Ink on every fill:
       success 12.40:1, info 13.70:1, warning 12.16:1, danger 14.01:1
     If you re-skin this theme toward a light register, these four are the
     first thing that breaks. CUSTOMIZE.md Move 1 shows exactly how.
     ---------------------------------------------------------------------- */
  --tv-fill-success: #16351f;
  --tv-fill-info: #12293f;
  --tv-fill-warning: #3a2f10;
  --tv-fill-danger: #3d1c1e;

  /* ----------------------------------------------------------------------
     BORDER
     Aesthetic philosophy axis. Two weights of the same idea. The hairline
     (1.68:1 on the ground) draws the resting edge of a tile and is meant
     to be quiet; it says "this is an object" without claiming attention,
     because the ring is what claims attention. The strong border is for
     boundaries that must be findable on their own without a ring on them:
     the hint bar's top edge, an input, a secondary button.
       border-strong on chrome 4.71:1, on ground 4.54:1, on surface 3.92:1,
       on surface-raised 3.09:1, all clearing the 3:1 UI-component floor
     ---------------------------------------------------------------------- */
  --tv-border-width: 1px;
  --tv-border: #343c46;         /* resting tile edge, dividers */
  --tv-border-strong: #737e8b;  /* control boundaries, chrome edges */

  /* ----------------------------------------------------------------------
     SHADOW
     Sensory ambition axis. Shadows do very little on a near-black ground,
     which is why this register spends its separation budget on fill steps
     and on the ring instead. What remains is a deep soft drop under a
     focused tile and under an open view, so those two read as lifted off
     the field rather than painted onto it. Pure black at low alpha, which
     is the only shadow that behaves on a dark ground.
     ---------------------------------------------------------------------- */
  --tv-shadow-tile: 0 1px 2px rgba(0, 0, 0, 0.4);
  --tv-shadow-raised: 0 6px 18px -6px rgba(0, 0, 0, 0.7);
  --tv-shadow-view: 0 -2px 40px -8px rgba(0, 0, 0, 0.8);

  /* ----------------------------------------------------------------------
     RADIUS
     Audience relationship axis. A 16px tile corner is the shape the eye
     resolves as "a card on a screen" at distance; smaller reads as square
     at ten feet and larger starts rounding into a lozenge. Controls sit at
     10px, chips at 6px.
     ---------------------------------------------------------------------- */
  --tv-radius-tight: 6px;    /* badges, chips, keyboard hints */
  --tv-radius: 10px;         /* buttons, inputs */
  --tv-radius-tile: 16px;    /* tiles and panels */
  --tv-radius-pill: 999px;

  /* ----------------------------------------------------------------------
     TYPE
     Tone register axis. System fonts, no webfont, no network request. The
     scale is shifted up bodily for the viewing distance described at the
     top of this file: the body size is 20px and the smallest size in the
     theme is 15px, which is the label on a tile. Weights run heavier than
     a desk register would: thin strokes disappear across a room, so the
     body weight is 450 and the display weight is 800.
     ---------------------------------------------------------------------- */
  --tv-font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --tv-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  --tv-weight-body: 450;
  --tv-weight-medium: 550;
  --tv-weight-bold: 700;
  --tv-weight-display: 800;

  --tv-text-display: 4rem;      /* 64px, the view's opening line */
  --tv-text-h1: 3rem;           /* 48px */
  --tv-text-h2: 2.25rem;        /* 36px, row headings */
  --tv-text-h3: 1.625rem;       /* 26px, tile labels */
  --tv-text-lead: 1.5rem;       /* 24px */
  --tv-text-body: 1.25rem;      /* 20px */
  --tv-text-sm: 1.0625rem;      /* 17px */
  --tv-text-xs: 0.9375rem;      /* 15px, the floor; nothing smaller ships */

  --tv-leading-tight: 1.05;
  --tv-leading-snug: 1.25;
  --tv-leading-body: 1.55;

  --tv-tracking-tight: -0.02em;
  --tv-tracking-wide: 0.06em;

  /* ----------------------------------------------------------------------
     SPACE
     Aesthetic philosophy axis. A fixed scale. The rail is the browse
     surface's side padding and it is generous on purpose: televisions
     overscan, and content pinned to the physical edge of a panel is
     content some rooms never see.
     ---------------------------------------------------------------------- */
  --tv-space-1: 4px;
  --tv-space-2: 8px;
  --tv-space-3: 12px;
  --tv-space-4: 16px;
  --tv-space-6: 24px;
  --tv-space-8: 32px;
  --tv-space-12: 48px;
  --tv-space-16: 64px;

  --tv-measure: 62ch;

  /* The column an opened view lays out in, which is deliberately NOT the
     measure. The measure is a prose rule: 62 characters is where a paragraph
     stops being comfortable, and paragraphs keep it. A 64px opening line does
     not become more readable in a 62ch column, it becomes a three-line stack
     with a ragged middle, and on a 1280 screen it leaves 300px of empty field
     on both sides while the headline is cramped. So headings, panels and
     lists get this width and prose limits itself. Found by rendering an open
     view at 1280 and looking at it. */
  --tv-view-width: 60rem;

  /* ----------------------------------------------------------------------
     MOTION
     Sensory ambition axis. Two things move and nothing else does: a tile
     grows a little when focus lands on it, and a row slides when focus
     leaves the visible part of it. Both are the same 140ms. Under
     prefers-reduced-motion the block at the bottom of this file collapses
     the duration to 1ms, which leaves both STATES intact and instant: the
     focused tile is still the larger one, the row is still scrolled to
     show it, and neither transition is animated. Removing the states
     rather than the animation would break the shell, because the scroll is
     what keeps the focused tile on screen.
     ---------------------------------------------------------------------- */
  --tv-duration: 140ms;
  --tv-ease: cubic-bezier(0.2, 0, 0, 1);
  --tv-focus-scale: 1.06;  /* how much a tile grows under focus */

  /* ----------------------------------------------------------------------
     FOCUS
     Audience relationship axis, and the single most important group in
     this file. On a shell with no pointer, the ring is not an
     accessibility afterthought bolted onto a design; it IS the design's
     hero element, and it is sized accordingly: 5px of accent, held 4px off
     the tile so the tile's own edge stays legible underneath it. At
     10.39:1 against the ground it is the highest-contrast object anywhere
     on the browse surface, which is the property the whole shell is built
     around. If you re-skin this theme, re-measure this pairing first.
     ---------------------------------------------------------------------- */
  --tv-ring: var(--tv-accent);
  --tv-ring-width: 5px;
  --tv-ring-offset: 4px;

  /* ----------------------------------------------------------------------
     SHELL GEOMETRY
     The group a register theme would not have: the measurements of the
     dashboard itself. shell/shell.css draws every part of it from these,
     so re-skinning the shell stays a one-file edit.

     The tile is 300 wide by 168 tall, near enough to 16:9, because the
     content a tile stands for on a screen like this is usually 16:9. Four
     of them plus the rail overflow a 1280 viewport by design: a row that
     runs off the edge is what tells a reader the row continues, and it is
     also what makes the row-scroll behaviour worth having.
     ---------------------------------------------------------------------- */
  --tv-tile-w: 300px;
  --tv-tile-h: 168px;
  --tv-tile-gap: 20px;
  --tv-row-gap: 12px;          /* between one row block and the next */
  --tv-rail: 48px;             /* side padding; overscan margin */
  --tv-hint-height: 64px;      /* the hint bar at the bottom edge */
  --tv-glyph-size: 44px;       /* the mark drawn on a tile */
  --tv-control-min: 48px;      /* smallest square a control may be */
  --tv-btn-min: 56px;          /* an in-view button; the couch floor, not the thumb floor */
  --tv-textarea-min: 140px;
  --tv-icon-sm: 20px;          /* an icon set inside a control */

  /* Layering. The browse surface sits at the bottom, an open view covers
     it, the hint bar is above both because it is always true, and the skip
     link is above everything. */
  --tv-z-rows: 10;
  --tv-z-view: 20;
  --tv-z-chrome: 30;
  --tv-z-skip: 50;
}

/* ----------------------------------------------------------------------
   THE NARROW OVERRIDES
   Under 768px the ten-foot dashboard becomes a two-column grid that stacks
   down the page; shell.css does the structural half of that transform and
   this block does the value half, so no length literal has to appear in a
   stylesheet that is supposed to hold none.

   The type scale comes down here and only here. Sizes chosen for a room
   are wrong in a hand: 64px of display type on a 390px screen is four
   words a line, and a 26px tile label does not fit two columns. Everything
   still clears the theme's 15px floor.
   ---------------------------------------------------------------------- */
@media (max-width: 767px) {
  :root {
    --tv-rail: 20px;
    --tv-tile-gap: 12px;
    --tv-tile-h: 148px;
    --tv-glyph-size: 30px;
    --tv-row-gap: 24px;

    --tv-text-display: 2.5rem;  /* 40px */
    --tv-text-h1: 2rem;         /* 32px */
    --tv-text-h2: 1.625rem;     /* 26px, row headings */
    --tv-text-h3: 1.25rem;      /* 20px, tile labels */
    --tv-text-lead: 1.25rem;    /* 20px */
    --tv-text-body: 1.0625rem;  /* 17px */
    --tv-text-sm: 1rem;         /* 16px, the input floor iOS wants */
  }
}

/* Anyone who has asked the system to stop animating gets two changes, and
   they are deliberately different from each other.

   The row scroll SURVIVES and only stops being animated. It has to: the
   scroll is what keeps the focused tile on screen, and a shell that leaves
   focus somewhere the reader cannot see is broken, not calm. shell.js reads
   the same preference and switches its scrolling from smooth to instant, so
   the two halves stay in agreement.

   The focus scale is REMOVED, not merely un-animated. A tile that jumps 6%
   larger the instant focus lands on it is still a thing that grew; running
   it in 1ms makes it a flinch rather than a movement, which is a worse
   answer than not doing it. It can be dropped outright because nothing
   depends on it: the ring is the design's hero element and is sized to
   carry focus by itself, so the reduced-motion board says exactly the same
   thing about where you are, in exactly one way instead of two.

   One consequence worth knowing about if you are capturing screenshots: a
   transform scales a tile to fractional pixel bounds, and the antialiasing
   along the ring at those bounds is not reproducible run to run (measured
   here at 18 pixels differing by up to 5/255 between otherwise identical
   captures). Removing the scale is therefore also what makes a focused
   board hashable, which is why every capture committed to this repo is a
   reduced-motion render. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --tv-duration: 1ms;
    --tv-focus-scale: 1;
  }
}
