/* ============================================================
   SKINS — one look, two surfaces, no capability.

   THE RULE THIS FILE EXISTS TO ENFORCE:

       A SKIN IS A LOOK. IT CARRIES NO PERMISSION AND NO DATA.

   Choosing the console skin on the public site must not reveal one
   operator number, one prospect, one contamination count. It changes
   the paint, nothing else.

   That is why this is a STYLESHEET rather than a shared template.
   admin.html references board., business., brands and /admin/ links
   in 30+ places; sharing that template with the public surface would
   mean guarding every one of them and getting it right forever. A
   stylesheet cannot leak a number it has never been given.

   TWO SKINS:

     search    the simple one. White, centred, a box and an answer.
               What most people want most of the time.

     console   the dark desk. Near-black panel, phosphor text, the
               screen lighting the room. For people who like the
               machine to look like a machine.

   Both are available on the public site and in the operator console.
   The operator surface has operator CONTENT either way; the public
   surface never does, in either skin.
   ============================================================ */

/* ---------------------------------------------- skin: search ---- */
/* The default. Deliberately plain: a person who came to look
   something up should not have to parse an interface first. */

[data-skin="search"] {
  --sk-bg: #ffffff;
  --sk-ink: #1a1a1a;
  --sk-dim: #5f6368;
  --sk-rule: #dfe1e5;
  --sk-field: #ffffff;
  --sk-accent: #1a73e8;
  --sk-face: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial,
             sans-serif;
  --sk-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --sk-radius: 24px;
  --sk-glow: none;
}

[data-skin="search"] body {
  background: var(--sk-bg);
  color: var(--sk-ink);
  font-family: var(--sk-face);
}

[data-skin="search"] .sk-field {
  background: var(--sk-field);
  border: 1px solid var(--sk-rule);
  border-radius: var(--sk-radius);
  padding: .7rem 1.1rem;
  font-size: 1rem;
  color: var(--sk-ink);
  box-shadow: none;
  transition: box-shadow .15s ease, border-color .15s ease;
}
[data-skin="search"] .sk-field:focus {
  outline: none;
  border-color: transparent;
  box-shadow: 0 1px 6px rgba(32, 33, 36, .28);
}

[data-skin="search"] .sk-panel {
  background: #fff;
  border: 1px solid var(--sk-rule);
  border-radius: 8px;
  padding: 1rem 1.2rem;
}

[data-skin="search"] .sk-value { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------- skin: console ---- */
/* The dark desk. Same structural classes, different paint - which is
   the whole point: markup written once renders in either skin. */

[data-skin="console"] {
  --sk-bg: #333333;
  --sk-ink: #f4f6f8;
  --sk-dim: #8b9099;
  --sk-rule: #2a2d33;
  --sk-field: #0d0e11;
  --sk-accent: #7fb4e6;
  --sk-face: "Cascadia Mono", "Cascadia Code", Consolas, ui-monospace,
             Menlo, monospace;
  --sk-mono: "Cascadia Mono", Consolas, ui-monospace, monospace;
  --sk-radius: 4px;
  /* Light escaping the panel. The one property that makes a dark
     surface read as LIT rather than merely painted dark. */
  --sk-glow: 0 0 60px -10px rgba(120, 175, 225, .28);
}

[data-skin="console"] body {
  /* PAGE GROUND #333333 - the room. The PANEL stays near-black, because a
     monitor is darker than the room around it and inverting that would undo
     the lighting model. Measured: panel-to-page contrast improves from
     1.08:1 to 1.45:1, so the screen reads as an object on a desk rather than
     dissolving into it. */
  background:
    radial-gradient(120% 90% at 50% 0%, #3a3a3a 0%, #333333 55%, #2a2a2a 100%);
  color: var(--sk-ink);
  font-family: var(--sk-face);
}

[data-skin="console"] .sk-field {
  background: var(--sk-field);
  border: 1px solid var(--sk-rule);
  border-radius: var(--sk-radius);
  padding: .6rem .9rem;
  font-family: var(--sk-mono);
  font-size: .95rem;
  color: var(--sk-ink);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, .55);
}
[data-skin="console"] .sk-field:focus {
  outline: none;
  border-color: #3f4650;
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, .55),
              0 0 0 3px rgba(127, 180, 230, .14);
}

[data-skin="console"] .sk-panel {
  position: relative;
  background: linear-gradient(180deg, #141518 0%, #0e0f12 100%);
  border: 1px solid var(--sk-rule);
  border-radius: var(--sk-radius);
  padding: 1rem 1.2rem;
  box-shadow: var(--sk-glow), inset 0 1px 0 rgba(190, 215, 240, .10);
}

/* The pixel grid, at the threshold of visible. Stronger reads as a
   pattern; absent reads as paint. */
[data-skin="console"] .sk-panel::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background:
    repeating-linear-gradient(180deg,
      rgba(255,255,255,.028) 0 1px, transparent 1px 3px);
}

/* Emitted text glows; printed text does not. Most of what separates a
   screen from a picture of one. */
[data-skin="console"] .sk-value {
  font-family: var(--sk-mono);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 14px rgba(170, 210, 255, .30);
}

/* ------------------------------------------------ the switcher ---- */
/* TOP RIGHT, TWO WEIGHTS, ONE POSITION.

   Same corner on both surfaces, because that is where people look for
   display and account controls. Different weight, because the two pages
   have different attention economies: the public search page is one box
   and a chunky toggle beside it would compete with the only thing that
   matters there. */

.sk-switch {
  position: fixed;
  top: .75rem;
  right: 1rem;
  z-index: 30;
  display: inline-flex;
  align-items: center;
  gap: .1rem;
  font-size: .8rem;
}
.sk-switch a {
  padding: .3rem .7rem;
  border-radius: 999px;
  text-decoration: none;
  color: var(--sk-dim);
  transition: color .15s ease, background .15s ease;
}
.sk-switch a:hover { color: var(--sk-ink); }
.sk-switch a:focus-visible {
  outline: 2px solid var(--sk-accent);
  outline-offset: 2px;
}

/* Public: a quiet text pair. The current skin is simply darker - no chip,
   no border, nothing to draw the eye away from the search box. */
[data-skin="search"] .sk-switch a[aria-current="true"] {
  color: var(--sk-ink);
  font-weight: 600;
}

/* Console: the page already has instruments, so the control can look like
   one. A lit pill matches the panels around it. */
[data-skin="console"] .sk-switch {
  border: 1px solid var(--sk-rule);
  border-radius: 999px;
  padding: 2px;
  background: rgba(10, 11, 13, .72);
  backdrop-filter: blur(6px);
}
[data-skin="console"] .sk-switch a[aria-current="true"] {
  background: rgba(127, 180, 230, .16);
  color: var(--sk-ink);
  box-shadow: inset 0 0 0 1px rgba(127, 180, 230, .28);
}

/* On a narrow screen the corner belongs to the content. */
@media (max-width: 640px) {
  .sk-switch { position: static; justify-content: flex-end; margin: .4rem 1rem 0; }
}

/* Nothing in either skin carries information by motion, so all of it
   stops without loss. */
@media (prefers-reduced-motion: reduce) {
  [data-skin] .sk-field { transition: none; }
}

/* ============================================================
   CONSOLE REALISM

   Four things a real dark screen does that a dark rectangle does not.
   Each one is physics, not decoration, which is why they are worth the
   bytes: the eye recognises them before it can say what it recognised.
   ============================================================ */

/* ---- 1. THE GLASS IS A MIRROR -------------------------------------
   THE BIGGEST SINGLE TELL, AND THE ONE I HAD MISSED.

   A powered-down screen is not black - it is a dark mirror. A powered-on
   one still reflects the room over the top of what it displays. A panel
   with no reflection reads as PAINT, however dark you make it.

   A broad diagonal sheen, barely there, is enough. It must stay under
   the content, so text is never veiled by it. */
[data-skin="console"] .sk-panel::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
  background:
    linear-gradient(105deg,
      transparent 0%,
      rgba(190, 215, 240, .028) 34%,
      rgba(190, 215, 240, .055) 44%,
      rgba(190, 215, 240, .018) 52%,
      transparent 70%);
}
[data-skin="console"] .sk-panel > * { position: relative; z-index: 1; }

/* ---- 2. THE GLASS IS CURVED ---------------------------------------
   Even a flat panel sits behind glass with a bevel, and a CRT genuinely
   bows. The tell is that the CORNERS lose light faster than the edges,
   and the bezel casts a soft shadow inward all the way round.

   Done with inset shadow rather than a transform: bending the element
   would bend the TEXT, and unreadable is a poor price for authentic. */
[data-skin="console"] .sk-panel {
  box-shadow:
    var(--sk-glow),
    inset 0 1px 0 rgba(190, 215, 240, .10),
    /* the bezel's shadow falling on the glass */
    inset 0 0 22px rgba(0, 0, 0, .55),
    /* corners darker than edges - the curvature tell */
    inset 0 0 70px -20px rgba(0, 0, 0, .8);
}

/* ---- 3. PHOSPHOR HAS COLOUR ---------------------------------------
   A CRT pixel is three separate dots. Text on one carries a faint colour
   fringe - warm on one side, cool on the other - because the beams do
   not land in exactly the same place.

   At this strength it is invisible as colour and visible as REALISM.
   Any stronger and it reads as a rendering fault. */
[data-skin="console"] .sk-value,
[data-skin="console"] .sk-emit {
  text-shadow:
    -0.4px 0 0.6px rgba(255, 138, 138, .22),
     0.4px 0 0.6px rgba(138, 208, 255, .22),
     0 0 14px rgba(170, 210, 255, .30);
}

/* Selection should look like phosphor, not like a browser default. */
[data-skin="console"] ::selection {
  background: rgba(127, 180, 230, .28);
  color: #ffffff;
}

/* ---- 4. THE BEAM SWEEPS, IT DOES NOT FLICKER ----------------------
   ONE PASS EVERY NINE SECONDS. Slow enough to read as a refresh and far
   too slow to strobe.

   A fast scanline is a photosensitivity hazard, not a style choice, and
   that is a hard line rather than a preference. */
[data-skin="console"] .sk-panel .sk-sweep {
  position: absolute;
  left: 0;
  right: 0;
  height: 34%;
  pointer-events: none;
  z-index: 2;
  background: linear-gradient(180deg,
    transparent, rgba(190, 220, 255, .05), transparent);
  animation: sk-sweep 9s linear infinite;
}
@keyframes sk-sweep {
  0%   { transform: translateY(-40%); }
  100% { transform: translateY(300%); }
}

/* ---- BEHAVIOUR: the caret is alive --------------------------------
   A terminal caret blinks about once a second. This is the one motion
   users EXPECT, and its absence is why a fake terminal feels dead.

   1.06s, matching the usual terminal rate. Fast enough to read as a
   cursor, slow enough that it is nowhere near flicker territory. */
[data-skin="console"] .sk-field {
  caret-color: #7fe6b4;
}
[data-skin="console"] .sk-caret {
  display: inline-block;
  width: .55em;
  height: 1.05em;
  vertical-align: text-bottom;
  background: #7fe6b4;
  box-shadow: 0 0 8px rgba(127, 230, 180, .7);
  animation: sk-blink 1.06s steps(1, end) infinite;
}
@keyframes sk-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* ---- BEHAVIOUR: the panel responds to focus -----------------------
   A real machine shows you where the input is going. */
[data-skin="console"] .sk-panel:focus-within {
  box-shadow:
    var(--sk-glow),
    inset 0 1px 0 rgba(190, 215, 240, .14),
    inset 0 0 22px rgba(0, 0, 0, .5),
    inset 0 0 70px -20px rgba(0, 0, 0, .75),
    0 0 0 1px rgba(127, 180, 230, .22);
}

/* Everything above is atmosphere, so all of it stops without losing a
   single piece of information. */
@media (prefers-reduced-motion: reduce) {
  [data-skin="console"] .sk-panel .sk-sweep { animation: none; display: none; }
  [data-skin="console"] .sk-caret { animation: none; opacity: 1; }
}

/* A struck key. 60ms, because anything slower reads as lag and lag is what
   makes an interface feel fake rather than fast. */
[data-skin="console"] .sk-field.sk-struck {
  border-color: #4a5560;
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, .7),
              0 0 0 3px rgba(127, 180, 230, .10);
}

/* ============================================================
   THE DESK LAMP

   A lamp is not an object you add to a scene. It is a LIGHT SOURCE, and
   adding one means re-lighting everything already there.

   The whole console scene has always been lit by two sources: the screen
   from above (cool) and a warm lamp from the left, just out of frame. This
   brings that lamp INTO frame on the left, where its light already came
   from - so nothing has to be re-reasoned, only made visible.

   ONE VARIABLE DRIVES EVERYTHING: --lamp, 0 to 1.

     0.0   off. The desk is lit ONLY by the screen - cool, blue, and the
           objects lose their warm side entirely. This is the honest look
           of a room at night with one monitor on.
     0.35  low. The warm pool reaches the near objects; the far side of
           the desk stays cool.
     1.0   full. Warm light dominates, the screen's contribution becomes
           the rim rather than the key.

   Every warm value below is multiplied by --lamp, so the dimmer is a real
   dimmer rather than three hand-drawn states.
   ============================================================ */

[data-skin="console"] {
  /* Off by default: the scene was designed screen-lit, and that is the
     look someone gets before touching anything. */
  --lamp: 0;
  /* Warmth of the bulb. Tungsten, not daylight - a cool "lamp" reads as a
     second monitor rather than a lamp. */
  --lamp-warm: 255, 176, 92;
}

/* ---- the pool of light on the desk -------------------------------- */
[data-skin="console"] .sk-desk {
  position: relative;
  background:
    /* WARM KEY from the lamp at the left. Scaled by --lamp, so at 0 this
       layer contributes nothing at all. */
    radial-gradient(120% 120% at 6% 22%,
      rgba(var(--lamp-warm), calc(.22 * var(--lamp))) 0%,
      rgba(var(--lamp-warm), calc(.08 * var(--lamp))) 32%,
      transparent 62%),
    /* COOL FILL from the screen above. Deliberately NOT scaled - the
       monitor does not dim when the lamp does, and forgetting that is how
       a scene ends up looking flat at low settings. */
    linear-gradient(180deg, rgba(150, 190, 225, .13) 0%, transparent 42%),
    /* the desk itself, warming slightly as the lamp comes up */
    linear-gradient(180deg,
      rgb(calc(23 + 26 * var(--lamp)), calc(19 + 15 * var(--lamp)), 15) 0%,
      #100d0b 55%, #0a0807 100%);
  transition: background .5s ease;
}

/* ---- the lamp itself ---------------------------------------------- */
[data-skin="console"] .sk-lamp { flex: none; align-self: flex-end; }
[data-skin="console"] .sk-lamp svg { width: 74px; height: auto; }

/* The bulb. Dark and dead at 0, and it must look genuinely OFF rather than
   dimly on - a lamp that never fully extinguishes reads as broken. */
[data-skin="console"] .sk-bulb {
  fill: rgb(calc(40 + 215 * var(--lamp)),
            calc(38 + 138 * var(--lamp)),
            calc(34 + 58 * var(--lamp)));
  transition: fill .4s ease;
}

/* The cone of light under the shade. */
[data-skin="console"] .sk-cone {
  fill: rgba(var(--lamp-warm), calc(.30 * var(--lamp)));
  transition: fill .4s ease;
}

/* Escaping glow, which is what actually sells a lit lamp - the bulb is
   small, the halo is what the eye reads. */
[data-skin="console"] .sk-halo {
  opacity: var(--lamp);
  transition: opacity .4s ease;
}

/* ---- objects gain a warm side as the lamp rises -------------------- */
/* At 0 they keep only their cool screen-lit edge; at 1 the warm rim is
   the stronger of the two. This is the part that makes the dimmer feel
   like light rather than like a slider. */
[data-skin="console"] .sk-lit {
  filter:
    drop-shadow(calc(3px + 5px * var(--lamp)) 6px 9px rgba(0, 0, 0, .7))
    drop-shadow(-2px 0 calc(3px * var(--lamp))
                rgba(var(--lamp-warm), calc(.45 * var(--lamp))));
  transition: filter .4s ease;
}

/* ---- the dimmer control -------------------------------------------- */
[data-skin="console"] .sk-dimmer {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .62rem;
  letter-spacing: .18em;
  color: var(--sk-dim);
}
[data-skin="console"] .sk-dimmer input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 76px;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg,
    #2a2d33 0%,
    rgba(var(--lamp-warm), .8) calc(var(--lamp) * 100%),
    #2a2d33 calc(var(--lamp) * 100%));
  outline: none;
}
[data-skin="console"] .sk-dimmer input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: #d8dde3;
  box-shadow: 0 0 6px rgba(var(--lamp-warm), calc(.9 * var(--lamp)));
  cursor: pointer;
}
[data-skin="console"] .sk-dimmer input[type="range"]::-moz-range-thumb {
  width: 12px; height: 12px; border: none;
  border-radius: 50%;
  background: #d8dde3;
  cursor: pointer;
}
[data-skin="console"] .sk-dimmer button {
  font: inherit;
  padding: .2rem .55rem;
  border-radius: 3px;
  border: 1px solid var(--sk-rule);
  background: transparent;
  color: var(--sk-dim);
  cursor: pointer;
}
[data-skin="console"] .sk-dimmer button[aria-pressed="true"] {
  color: #ffd9a8;
  border-color: rgba(var(--lamp-warm), .5);
}
[data-skin="console"] .sk-dimmer input:focus-visible,
[data-skin="console"] .sk-dimmer button:focus-visible {
  outline: 2px solid var(--sk-accent);
  outline-offset: 2px;
}

/* The transitions are the light coming up, not decoration - but a person
   who has asked for less motion still gets the full range, instantly. */
@media (prefers-reduced-motion: reduce) {
  [data-skin="console"] .sk-desk,
  [data-skin="console"] .sk-bulb,
  [data-skin="console"] .sk-cone,
  [data-skin="console"] .sk-halo,
  [data-skin="console"] .sk-lit { transition: none; }
}

/* The lamp control sits with the skin switcher - both answer "how does this
   look", and splitting them would make a person hunt for the second one. */
[data-skin="console"] .sk-dimmer {
  position: fixed;
  top: 2.6rem;
  right: 1rem;
  z-index: 50;
  padding: .3rem .55rem;
  border: 1px solid var(--sk-rule);
  border-radius: 999px;
  background: rgba(10, 11, 13, .72);
  backdrop-filter: blur(6px);
}
@media (max-width: 640px) {
  [data-skin="console"] .sk-dimmer { position: static; margin: .4rem 1rem 0; }
}

/* ============================================================
   PLAIN PAGES INHERIT THE COLOURS.

   THE GAP THIS CLOSES: every page carried data-skin and NOTHING READ IT. The
   attribute was set, the stylesheet was loaded, and the word lists rendered
   in browser defaults - so a person who chose Compute saw one dark page and a
   dozen white ones.

   THESE PAGES ARE MEANT TO BE PLAIN. Word lists, concept lists, info pages -
   they are lists, and they should stay lists. This gives them the SKIN'S
   COLOURS and nothing else: no panels, no glow, no console furniture. The
   look is a palette, not a costume.

   Selectors are element-level and unqualified on purpose, so a page written
   next year inherits without anyone remembering to add a class.
   ============================================================ */

[data-skin] body {
  background: var(--sk-bg);
  color: var(--sk-ink);
  font-family: var(--sk-face);
}

[data-skin] a { color: var(--sk-accent); }
[data-skin] a:visited { color: var(--sk-accent); opacity: .82; }

[data-skin] h1, [data-skin] h2, [data-skin] h3,
[data-skin] h4, [data-skin] h5, [data-skin] h6 { color: var(--sk-ink); }

[data-skin] hr { border: none; border-top: 1px solid var(--sk-rule); }

/* Tables are what most of these pages ARE. Zebra striping from the rule
   colour rather than a fixed grey, so it works on both grounds. */
[data-skin] table { border-collapse: collapse; color: var(--sk-ink); }
[data-skin] th, [data-skin] td {
  border-bottom: 1px solid var(--sk-rule);
  padding: .35rem .6rem;
  text-align: left;
}
[data-skin] th { color: var(--sk-dim); font-weight: 600; }
[data-skin] tbody tr:nth-child(even) {
  background: color-mix(in srgb, var(--sk-rule) 22%, transparent);
}

/* Numbers line up in a list of counts. */
[data-skin] td.num, [data-skin] .count { font-variant-numeric: tabular-nums; }

[data-skin] code, [data-skin] pre, [data-skin] kbd {
  font-family: var(--sk-mono);
  background: color-mix(in srgb, var(--sk-rule) 30%, transparent);
  border-radius: 3px;
  padding: .05em .3em;
}

[data-skin] input, [data-skin] select, [data-skin] textarea,
[data-skin] button {
  font: inherit;
  color: var(--sk-ink);
  background: var(--sk-field);
  border: 1px solid var(--sk-rule);
  border-radius: 4px;
  padding: .35rem .6rem;
}
[data-skin] button { cursor: pointer; }
[data-skin] input:focus-visible, [data-skin] select:focus-visible,
[data-skin] textarea:focus-visible, [data-skin] button:focus-visible {
  outline: 2px solid var(--sk-accent);
  outline-offset: 1px;
}

/* ---- home link, top left ------------------------------------------
   Opposite corner from the skin switcher, so the two never collide, and
   in the place people already reach for to get back. */
.sk-home {
  position: fixed;
  top: .75rem;
  left: 1rem;
  /* BELOW the sticky list header, not above it. A fixed control that
     overlaps a sticky bar is the collision this commit removes. */
  z-index: 30;
  font-size: .82rem;
  text-decoration: none;
  padding: .3rem .7rem;
  border-radius: 999px;
  color: var(--sk-dim);
}
.sk-home:hover { color: var(--sk-ink); }
.sk-home:focus-visible {
  outline: 2px solid var(--sk-accent);
  outline-offset: 2px;
}
[data-skin="console"] .sk-home {
  border: 1px solid var(--sk-rule);
  background: rgba(10, 11, 13, .72);
  backdrop-filter: blur(6px);
}
@media (max-width: 640px) {
  .sk-home { position: static; display: inline-block; margin: .4rem 0 0 1rem; }
}

/* ---- the list header — ONE STICKY BAR -----------------------------
   Home, title, count, search and Browse travel together.

   THE BUG THIS FIXES: home and the skin switcher were `fixed` while the
   title and search were static, so on a long list the search box scrolled up
   and passed BEHIND the two fixed buttons. The controls a person needs most
   disappeared exactly when the list was long enough to need them.

   `sticky` rather than `fixed`, because a fixed bar occupies space the
   document does not know about and the first rows hide underneath it. */
.sk-listhead {
  position: sticky;
  top: 0;
  z-index: 40;
  margin: 0 0 1.2rem;
  padding: .7rem 0 .8rem;
  border-bottom: 1px solid var(--sk-rule);
  /* OPAQUE. A translucent sticky bar with list rows sliding under it is
     unreadable at exactly the moment it matters. */
  background: var(--sk-bg);
}
.sk-listhead h1 {
  font-size: 1.1rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  margin: 0 0 .7rem;
}
.sk-listhead h1 a { color: var(--sk-ink); text-decoration: none; }
.sk-listhead h1 a:hover { text-decoration: underline; }
.sk-listcount {
  font-weight: 400;
  opacity: .62;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
.sk-listsearch { margin: 0 0 .6rem; }

/* The Browse accordion opens INSIDE the sticky bar, so a long tree would
   pin the whole page. Capped and scrollable instead. */
.sk-listhead .sk-langtree {
  max-height: 40vh;
  overflow-y: auto;
}

.sk-listsearch input { width: min(28rem, 100%); }

/* ---- the language accordion --------------------------------------- */
.sk-langpick { font-size: .82rem; }
.sk-langtoggle,
.sk-langnode {
  font: inherit;
  background: none;
  border: none;
  color: var(--sk-ink);
  cursor: pointer;
  padding: .18rem 0;
  text-align: left;
}
.sk-langtoggle:focus-visible,
.sk-langnode:focus-visible {
  outline: 2px solid var(--sk-accent);
  outline-offset: 2px;
}
.sk-arrow {
  display: inline-block;
  width: 1em;
  opacity: .62;
}
.sk-langcurrent { opacity: .7; }
.sk-langcount { opacity: .55; font-variant-numeric: tabular-nums; }
.sk-langtree { margin: .3rem 0 0; }
.sk-langbranch,
.sk-langleaves { list-style: none; margin: 0; padding-left: 1.05rem; }
.sk-langkids { margin-left: .1rem; }
.sk-langleaves a { text-decoration: none; }
.sk-langleaves a:hover { text-decoration: underline; }
.sk-langnote {
  margin: 0 0 .4rem;
  font-size: .72rem;
  opacity: .7;
}

/* A branch with no words yet. DIMMED, NOT HIDDEN - it is the work queue,
   and the point of showing the whole tree. */
.sk-langempty { opacity: .45; }
.sk-langtodo { opacity: .8; }

/* ---- ask Peter ----------------------------------------------------
   Sits with the search box because it is the same act - you have typed a
   thing and you want an answer about it. */
.sk-ask, .sk-mic {
  font: inherit;
  font-size: .78rem;
  margin-left: .35rem;
  padding: .3rem .7rem;
  border: 1px solid var(--sk-rule);
  border-radius: 999px;
  background: transparent;
  color: var(--sk-dim);
  cursor: pointer;
}
.sk-ask:hover, .sk-mic:hover { color: var(--sk-ink); }
.sk-ask:disabled, .sk-mic:disabled { opacity: .4; cursor: default; }
.sk-ask:focus-visible, .sk-mic:focus-visible {
  outline: 2px solid var(--sk-accent);
  outline-offset: 2px;
}

/* LISTENING IS OBVIOUS. A microphone that is recording and does not look
   like it is recording is the one state that must never be ambiguous.
   Colour AND a ring, because colour alone is not a signal everyone gets. */
.sk-mic-live {
  color: #ff8a8a;
  border-color: #ff8a8a;
  box-shadow: 0 0 0 3px rgba(255, 138, 138, .18);
}

.sk-askpanel {
  margin: .6rem 0 0;
  padding: .7rem .9rem;
  border: 1px solid var(--sk-rule);
  border-radius: 6px;
  font-size: .84rem;
  max-width: 52rem;
}
.sk-askanswer { margin: 0 0 .5rem; white-space: pre-wrap; }
.sk-asknote { margin: 0; font-size: .72rem; opacity: .65; }
.sk-askclose {
  font: inherit;
  font-size: .72rem;
  margin-top: .5rem;
  padding: .15rem .5rem;
  border: 1px solid var(--sk-rule);
  border-radius: 4px;
  background: transparent;
  color: var(--sk-dim);
  cursor: pointer;
}
.sk-ask-error { border-color: #d08a8a; }
.sk-ask-waiting { opacity: .7; }

/* Direction arrows on a detail page. Left is upstream, right is downstream -
   and the words say so too, because an arrow alone is a convention not
   everyone shares. */
.sk-dir {
  display: inline-block;
  width: 1.2em;
  opacity: .7;
  font-variant-numeric: tabular-nums;
}

/* Home and skin INSIDE the sticky bar. The floating rules still apply on
   pages with no bar, so `.sk-inbar` unsets only what makes them float. */
.sk-listbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 .5rem;
}
.sk-inbar {
  position: static;
  top: auto;
  left: auto;
  right: auto;
  margin: 0;
}

/* ---- the index bar ------------------------------------------------
   Same component top and bottom. The TOP one lives inside the sticky
   header; the BOTTOM one does not stick, because its job is pagination
   after a scroll rather than navigation during one. */
.sk-indexbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .1rem;
  font-size: .8rem;
}
.sk-indexbar-top { margin: .2rem 0 0; }
.sk-indexbar-bottom {
  margin: 1.6rem 0 0;
  padding-top: .8rem;
  border-top: 1px solid var(--sk-rule);
}
.sk-idx-cell,
.sk-idx-arrow {
  padding: .18rem .42rem;
  border-radius: 3px;
  text-decoration: none;
  color: var(--sk-dim);
}
.sk-idx-cell:hover,
.sk-idx-arrow:hover { color: var(--sk-ink); }
.sk-idx-here {
  color: var(--sk-ink);
  font-weight: 600;
  background: color-mix(in srgb, var(--sk-rule) 40%, transparent);
}
/* DISABLED, NOT HIDDEN. A control that disappears moves the ones beside it
   and is harder to understand than one visibly unavailable. */
.sk-idx-off {
  opacity: .3;
  pointer-events: none;
}
.sk-idx-pos {
  margin-left: .4rem;
  opacity: .55;
  font-variant-numeric: tabular-nums;
}
.sk-idx-cell:focus-visible,
.sk-idx-arrow:focus-visible {
  outline: 2px solid var(--sk-accent);
  outline-offset: 1px;
}

/* Column layout. The COUNT is decided by list intelligence; only the
   drawing happens here. */
.sk-cols-1 { column-count: 1; }
.sk-cols-2 { column-count: 2; }
.sk-cols-3 { column-count: 3; }
.sk-cols-4 { column-count: 4; }
[class*="sk-cols-"] { column-gap: 2rem; }
[class*="sk-cols-"] li { break-inside: avoid; }
@media (max-width: 900px) { [class*="sk-cols-"] { column-count: 2; } }
@media (max-width: 560px) { [class*="sk-cols-"] { column-count: 1; } }

/* Script view sits with the language menu — same question, same place. */
.sk-translit { margin: .35rem 0 0; font-size: .8rem; }
.sk-translit select { font-size: .8rem; padding: .2rem .4rem; }

/* List-type switcher — operator only, beside Browse. */
.sk-listpick { margin: .35rem 0 0; font-size: .8rem; }
.sk-listpick select { font-size: .8rem; padding: .2rem .4rem; max-width: 22rem; }
.sk-listall { margin-left: .5rem; font-size: .76rem; opacity: .7; }

/* Sign in / sign out — right-hand end of the bar, beside the skin switcher.
   SAME POSITION IN BOTH SKINS; only the colours differ, which is what a
   skin is for. */
.sk-account { margin-left: auto; margin-right: .6rem; font-size: .8rem; }
.sk-account a { text-decoration: none; color: var(--sk-dim); }
.sk-account a:hover { color: var(--sk-ink); text-decoration: underline; }
.sk-account a:focus-visible {
  outline: 2px solid var(--sk-accent);
  outline-offset: 2px;
}
/* In the console skin it reads as a control rather than body text, matching
   the other console furniture. */
[data-skin="console"] .sk-account a {
  border: 1px solid var(--sk-rule);
  border-radius: 999px;
  padding: .18rem .6rem;
}

/* ---- the skin selector, as a dropdown -----------------------------
   It was two links side by side - "Search Compute" - which reads as two
   buttons rather than one setting with a current value. A select shows the
   CURRENT view and opens to reveal the alternatives, which is what choosing
   a view is. */
.sk-switch select {
  font: inherit;
  font-size: .8rem;
  padding: .22rem 1.6rem .22rem .55rem;
  border: 1px solid var(--sk-rule);
  border-radius: 4px;
  background: var(--sk-field);
  color: var(--sk-ink);
  cursor: pointer;
  /* The native arrow is drawn by the platform and differs per browser; a
     consistent one keeps the control looking the same in both skins. */
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right .72rem center, right .5rem center;
  background-size: .3em .3em, .3em .3em;
  background-repeat: no-repeat;
}
.sk-switch select:hover { border-color: var(--sk-accent); }
.sk-switch select:focus-visible {
  outline: 2px solid var(--sk-accent);
  outline-offset: 1px;
}
/* In the console skin it reads as instrument furniture, matching the other
   controls there. Position is set once, outside any skin rule - A SKIN IS A
   LOOK, NOT A LAYOUT. */
[data-skin="console"] .sk-switch select {
  border-radius: 999px;
  letter-spacing: .04em;
}

/* ---- the drawn listbox ---------------------------------------------
   A native select's open list is drawn by the OS and cannot be styled, so
   the checkmark, the row highlight and a consistent look in both skins need
   markup we control. */
.sk-switch[data-skin-picker] { position: relative; }
.sk-skinbtn {
  font: inherit;
  font-size: .8rem;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .22rem .55rem;
  border: 1px solid var(--sk-rule);
  border-radius: 4px;
  background: var(--sk-field);
  color: var(--sk-ink);
  cursor: pointer;
}
.sk-skinbtn:hover { border-color: var(--sk-accent); }
.sk-skinbtn:focus-visible {
  outline: 2px solid var(--sk-accent);
  outline-offset: 1px;
}
.sk-skinbtn-caret { font-size: .7em; opacity: .7; }

.sk-skinlist {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 60;
  margin: 0;
  padding: .25rem 0;
  min-width: 9rem;
  list-style: none;
  background: var(--sk-bg);
  border: 1px solid var(--sk-rule);
  border-radius: 5px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
}
.sk-skinlist:focus { outline: none; }   /* the highlighted row shows focus */

.sk-skinopt {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .28rem .7rem .28rem .45rem;
  font-size: .8rem;
  color: var(--sk-ink);
  cursor: pointer;
  white-space: nowrap;
}
/* THE TICK COLUMN IS ALWAYS RESERVED, so labels do not shift sideways as
   the selection moves. */
.sk-skintick {
  display: inline-block;
  width: .85em;
  text-align: center;
  font-size: .85em;
}
/* ONE HIGHLIGHT FOR POINTER AND KEYBOARD. Two would let them disagree, and
   then Enter chooses a row the person is not looking at. */
.sk-skinopt-hot {
  background: var(--sk-accent);
  color: var(--sk-bg);
}
[data-skin="console"] .sk-skinlist { border-radius: 3px; }

/* The home menu reuses the skin listbox entirely; it only opens the other
   way, because it sits at the left edge. */
.sk-home-menu .sk-skinlist { right: auto; left: 0; }
/* A RULE BETWEEN PUBLIC AND OPERATOR DESTINATIONS. They are different kinds
   of place, and a flat list of eleven reads as one undifferentiated pile. */
.sk-skinsep {
  height: 1px;
  margin: .25rem .45rem;
  background: var(--sk-rule);
}

/* ---- the account bar ------------------------------------------------
   A thin strip above everything. It is a different kind of control from
   navigation - who you are, not where you are going - so it gets its own
   row rather than competing for the same corner. */
.sk-accountbar {
  position: sticky;
  top: 0;
  z-index: 80;          /* above the list bar, which is z-index 50 */
  background: var(--sk-bg);
  border-bottom: 1px solid var(--sk-rule);
}
.sk-accountbar-inner {
  display: flex;
  justify-content: flex-end;   /* top RIGHT corner, per the reference */
  align-items: center;
  gap: .5rem;
  padding: .2rem .9rem;
  min-height: 1.9rem;
}
.sk-acct-link {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .78rem;
  color: var(--sk-dim);
  text-decoration: none;
}
.sk-acct-link:hover { color: var(--sk-ink); text-decoration: underline; }
.sk-acct-icon { font-size: .95em; opacity: .85; }
.sk-acct-btn {
  border-color: transparent;
  background: transparent;
  color: var(--sk-dim);
  padding: .12rem .35rem;
}
.sk-acct-btn:hover { color: var(--sk-ink); border-color: var(--sk-rule); }

/* DISABLED, NOT HIDDEN. Hiding them would suggest the feature does not
   exist; greyed says it is not built yet, which is the truth. */
.sk-skinopt-off {
  opacity: .45;
  cursor: default;
}
.sk-skinopt-off:hover { background: none; color: inherit; }

/* The main bar sits BELOW the account bar rather than at the viewport top,
   or the two overlap when both are stuck. */
.sk-listhead { top: 1.9rem; }

/* ---- the desk scene, on the Compute skin -----------------------------
   THREE PHOTOGRAPHS, CROSS-FADED BY --lamp.

   The lamp used to be drawn entirely in CSS. These are real frames of the
   same desk at three light levels, which no gradient reproduces - the warm
   pool on the wall, the plant catching light, the keyboard legends coming up
   out of the dark.

   WHY A MIDDLE FRAME MATTERS FOR A TWO-STATE SWITCH: a real lamp does not
   jump. For a moment as it comes up it sits somewhere between, and the eye
   knows the difference. Fading off -> middle -> on reads as a lamp warming;
   fading off -> on reads as an image swap.

   All three frames are 1672x940, so they cross-fade without a shift.

   STACKED, NOT SWAPPED. Swapping a src leaves a blank while the new file
   decodes; layering all three and moving opacity means every frame is
   already decoded before it is needed. */
[data-skin="console"] .sk-scene {
  position: fixed;
  inset: 0;
  z-index: -1;            /* behind everything, never intercepts a click */
  pointer-events: none;
  overflow: hidden;
  background: #0b0a09;    /* the darkest frame's ground, for letterboxing */
}
[data-skin="console"] .sk-scene img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The eye reads a lamp as warming over a beat, not snapping. Slower than
     a UI transition on purpose. */
  transition: opacity .45s ease-in-out;
}

/* OFF is the base layer and always painted. The other two fade in over it,
   so there is never a frame with nothing behind it. */
[data-skin="console"] .sk-scene-off    { opacity: 1; }
/* MIDDLE peaks halfway and falls away at both ends - that is what makes the
   travel read as a lamp coming up rather than a cut. */
[data-skin="console"] .sk-scene-middle {
  opacity: calc(1 - (2 * (var(--lamp, 0) - 0.5)) * (2 * (var(--lamp, 0) - 0.5)));
}
[data-skin="console"] .sk-scene-on     { opacity: var(--lamp, 0); }

/* The scene is the Compute skin only. The Search skin is a document, and a
   photograph behind text is a different product. */
[data-skin="search"] .sk-scene { display: none; }

/* ---- the live clock, over the printed one ---------------------------
   All three frames show 9:23 on 6-30-FRI. This panel covers that rectangle
   and shows the reader's own time.

   MEASURED FROM THE FRAME, NOT GUESSED: the LCD occupies 86.84%..95.63%
   across and 59.57%..73.29% down of a 1672x940 image. Percentages because
   the scene is object-fit: cover - fixed pixels would drift off the lamp
   the moment the window changed shape. */
[data-skin="console"] .sk-clock {
  position: absolute;
  left: 86.84%;
  top: 59.57%;
  width: 8.79%;
  height: 13.72%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* The panel's own ground, so the printed digits underneath cannot show
     through at any lamp level. */
  background: #0a0a0b;
  border-radius: 8% / 9%;
  overflow: hidden;
  font-variant-numeric: tabular-nums;
  /* THE THREE LIGHT SETTINGS. A real LCD is brightest in the dark and
     washes out under a lamp - so the digits DIM as --lamp rises, which is
     the opposite of the rest of the scene and is what makes it read as a
     screen rather than a sticker. */
  color: rgba(255, 246, 228, calc(1 - (0.35 * var(--lamp, 0))));
  transition: color .45s ease-in-out;
}
[data-skin="console"] .sk-clock-time {
  font-size: clamp(.7rem, 2.6cqw, 2.1rem);
  line-height: 1;
  letter-spacing: .02em;
}
[data-skin="console"] .sk-clock-date {
  font-size: clamp(.4rem, 1.2cqw, .95rem);
  line-height: 1;
  margin-top: .28em;
  letter-spacing: .12em;
  opacity: .82;
}
/* The scene is the container the clock sizes against, so the digits scale
   with the photograph rather than with the viewport. */
[data-skin="console"] .sk-scene { container-type: size; }

/* The clock format controls, under the lamp. Compute skin only - a clock
   format selector on a page with no clock is clutter. */
[data-skin="console"] .sk-clock-prefs {
  position: absolute;
  left: 84%;
  top: 74.5%;
  display: flex;
  gap: .3rem;
  /* The scene is pointer-events: none so it never eats a click; these
     controls have to opt back in. */
  pointer-events: auto;
}
[data-skin="console"] .sk-clock-prefs select {
  font: inherit;
  font-size: .62rem;
  padding: .1rem .2rem;
  border: 1px solid var(--sk-rule);
  border-radius: 3px;
  background: var(--sk-field);
  color: var(--sk-ink);
  /* They belong to the lamp, not the page, so they stay quiet until
     somebody looks for them. */
  opacity: .35;
  transition: opacity .2s ease;
}
[data-skin="console"] .sk-clock-prefs:hover select,
[data-skin="console"] .sk-clock-prefs select:focus-visible { opacity: 1; }
[data-skin="search"] .sk-clock-prefs { display: none; }

/* ---- content inside the monitor -------------------------------------
   THE CONSOLE SKIN PUTS THE PAGE ON THE SCREEN IN THE PHOTOGRAPH. That was
   working against the old scene and the new frames moved every edge, so the
   panel is re-measured rather than re-guessed.

   MEASURED, NOT ESTIMATED: walked outward from the centre of each screen
   until brightness rose - the bezel. Monitor 993x515 at (400,58) of
   1672x940; laptop 382x274 at (22,412).

   Percentages throughout, because the scene is object-fit: cover and any
   fixed pixel drifts off the glass as soon as the window changes shape. */
[data-skin="console"] .site-main {
  position: fixed;
  left: 23.92%;
  top: 6.17%;
  width: 59.39%;
  height: 54.79%;
  margin: 0;
  padding: 1.1rem 1.3rem;
  overflow-y: auto;
  overflow-x: hidden;
  /* The glass is already black in the photograph. A faint wash separates
     text from it without hiding the panel underneath. */
  background: rgba(6, 8, 11, .82);
  color: var(--sk-ink);
  /* SCROLL INSIDE THE SCREEN, not the page. A monitor whose content runs
     off the bottom of the desk is not a monitor. */
  scrollbar-width: thin;
  font-size: .82rem;
  container-type: inline-size;
}
/* The screen is small, so the type inside it has to be. Set once here
   rather than per-page, or every new page would need remembering. */
[data-skin="console"] .site-main h1 { font-size: 1.05rem; }
[data-skin="console"] .site-main h2 { font-size: .88rem; }
[data-skin="console"] .site-main table { font-size: .74rem; }

/* ---- the business portal, on the laptop -----------------------------
   OPERATOR ONLY. The laptop is a second machine on the desk, and what it
   shows - prospects, the builder, the CRM - is the business side. A visitor
   has no account and no reason to see that these pages exist. */
[data-skin="console"] .sk-laptop {
  position: fixed;
  left: 1.32%;
  top: 43.83%;
  width: 22.85%;
  height: 29.15%;
  padding: .5rem .55rem;
  overflow-y: auto;
  background: rgba(6, 8, 11, .78);
  font-size: .62rem;
  line-height: 1.5;
  z-index: 1;
}
[data-skin="console"] .sk-laptop h2 {
  margin: 0 0 .35rem;
  font-size: .58rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--sk-dim);
}
[data-skin="console"] .sk-laptop a {
  display: block;
  padding: .12rem 0;
  color: var(--sk-ink);
  text-decoration: none;
}
[data-skin="console"] .sk-laptop a:hover { text-decoration: underline; }

/* Neither belongs on the Search skin - that is a document, not a desk. */
[data-skin="search"] .sk-laptop { display: none; }

/* ---- what the corpus holds, on the front page ----------------------- */
.home-counts { margin: 0 0 1.4rem; }
.home-counts-list {
  display: flex;
  flex-wrap: wrap;
  gap: 1.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.home-counts-list li { display: flex; flex-direction: column; }
.home-count-value {
  font-size: 1.35rem;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--sk-ink);
}
.home-count-label {
  font-size: .7rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--sk-dim);
}
/* SAYING THEY ARE APPROXIMATE, quietly but present. A visitor who assumes
   "1.8M" is exact has been misled by omission. */
.home-counts-note {
  margin: .6rem 0 0;
  font-size: .7rem;
  color: var(--sk-dim);
}
/* The console screen is small - the row wraps rather than overflowing the
   glass. */
[data-skin="console"] .home-counts-list { gap: .9rem; }
[data-skin="console"] .home-count-value { font-size: 1rem; }

/* The id beside a label: present for copying, quiet enough that the label
   is what the eye lands on. */
.sk-rowid { color: var(--sk-dim); font-size: .82em; }
