/* ====================================================================
   landing.css - the splash, and the only page a stranger sees first.

   ####################################################################
   ##            THIS PAGE IS HARMONISED, NOT REDESIGNED.  (SB-5)    ##
   ####################################################################

   The landing page has been off-limits for six waves because the owner
   said early on that he did not want to lose it, and the rest of the
   site has moved a long way since. What that produced was not a page
   that looked older -- it looked like a DIFFERENT SITE: neutral black
   next to blue-black, hard-coded greys next to a measured ink ramp,
   pure-white hairlines next to edges that know where the light is.

   SO THE TEST FOR EVERY LINE BELOW IS: somebody who loved this page
   should not be able to say what changed, only that it looks better
   made. Nothing here moved, nothing was removed, nothing was added.
   What changed is what the existing declarations are painted WITH:

     * BLACK -> the ground.        Solid #000 surfaces resolve to --void
       (#06070C) and the translucent ones compose it through --void-rgb.
       Four units of blue. Invisible on its own; the reason the page
       stops reading as a neutral patch when a red or a yellow glow
       crosses the seam between it and anything else on this site.
     * GREY -> the ink ramp.       #eee/#ccc/#999/#888/#666 were five
       hand-picked neutrals; they are now --text/--text-2/--text-dim/
       --text-3/--text-faint. THE MAPPING IS BY MEASURED CONTRAST, not by
       eye, which is why #888 lands on --text-3 and #999 on --text-dim
       rather than both on whichever token looked about right: against
       this page's panel, #eee is 17.2:1 and --text is 17.0, #ccc is 12.4
       and --text-2 is 12.6, #999 is 7.0 and --text-dim is 7.1, #888 is
       5.6 and --text-3 is 5.9. Four substitutions inside a tenth of a
       stop, i.e. four you cannot see.

       ONE IS DELIBERATELY NOT INVISIBLE. #666 -> --text-faint moves the
       waiver text and the login/register toggle from 3.5:1 to 4.8:1,
       because 3.5 is below AA and the paragraph carrying it is a legal
       disclaimer. It is the one contrast on this page that was actually
       failing, and the ink ramp starts at --text-faint precisely so that
       there is no legal way to reproduce the old value.
     * LINES -> the line ramp.     #333/#444 -> --c-line/--c-line-2, and
       the pure-white hairline on the two corner buttons -> --edge-e2,
       at the same 0.20 alpha it already had.
     * RED -> the classification ink. --c-red has resolved to #FF3B5C
       since the token wave, so most of this page moved with it already.
       Two did not, and they are fixed here: the roulette readout's glow,
       which was the retired #ff2a00 hiding as an rgb triple, and the
       auth error line's `color: red` in the view.
     * FACES -> the token stacks.  'Bebas Neue' / 'Courier Prime' /
       'Rubik Glitch' were bare names with no fallback, and the Google
       Fonts request that provides them is render-blocking: any failure
       dropped this page to the browser default. --font-ui / --font-mono
       / --font-display are the same faces with the site's fallbacks
       behind them.

   AND THREE SURFACES GET THE ELEVATION TREATMENT, which on this page
   means the LIGHTING and not the glass -- see depth.css rule 1. There is
   no backdrop-filter added anywhere below: the ember canvas and the
   thermal layer show through this page's panels on purpose, and blurring
   them would be the one change everybody would notice. The three are the
   HUD box, the roulette panel and the input well, and each is commented
   where it sits.

   ORDERING: views/layouts/landing.php links tokens.css and then this
   file, so every name above resolves and the one :root block below wins
   on the single token this page disagrees about.
   ==================================================================== */

/*
 * The two page-local names, plus the one token this page overrides.
 *
 *   --c-panel   the landing page's HUD box is TRANSLUCENT -- the ember canvas and
 *               the thermal layer show through it. tokens.css reconciles --c-panel
 *               to the dashboard's opaque panel surface, so it is overridden back
 *               here. This :root loads after tokens.css and therefore wins, and
 *               025_theme_contract_test.php pins the value: a HUD box that stops
 *               being translucent is a HUD box with the embers switched off behind
 *               it. It is the one colour on this page NOT re-pointed at the ground,
 *               and at 96% opacity the four units between it and --void are not a
 *               thing any eye resolves.
 *
 *   --void-rgb  --void, written as a triple.
 *
 *               tokens.css gives each of the four SIGNALS an -rgb triple so a
 *               component can compose its own alpha without re-typing a hex; it
 *               gives the GROUND none, because no screen surface had ever needed the
 *               ground at partial opacity. This page needs it at three -- the login
 *               trigger, the modal scrim and the thermal layer are all "the room,
 *               most of the way up" -- and rgba() cannot take a var() colour. It is
 *               the one value in this file duplicated from tokens.css, and it is
 *               named here rather than inlined three times so that there is exactly
 *               one place to correct if the ground ever moves.
 *
 *   --cursor-*  written by landing.js on every mousemove to drive the thermal
 *               flashlight mask. Page-local by nature.
 */
:root {
    --c-panel: rgba(10, 8, 8, 0.96);
    --void-rgb: 6, 7, 12;
    --cursor-x: 50%;
    --cursor-y: 50%;
}

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

/*
 * BUTTON RESET - the whole cost of making this page usable from a keyboard.
 *
 * Three controls here were a <div> or a <span> with an onclick: the login trigger,
 * the login/register toggle and [ ABORT SEQUENCE ]. None of them was focusable, none
 * had a role, and none fired on Enter or Space -- which meant a keyboard-only visitor
 * could not sign in to this site at all. They are real <button type="button"> now,
 * carrying the same classes, and these six declarations are what make a <button>
 * render identically to the element it replaced.
 *
 * It sits ABOVE the three rules it applies to, deliberately: `font: inherit` and
 * `color: inherit` would otherwise clobber .toggle-link's own 0.8rem/faint and
 * .login-trigger's --c-red. Ordered this way, each component's own declarations win
 * and only the UA defaults are neutralised.
 *
 * padding and margin are already zeroed by the `*` rule above, so they are not
 * repeated here.
 */
.login-trigger,
.toggle-link,
.abort-link {
    appearance: none;
    -webkit-appearance: none;
    background: none;
    border: 0;
    font: inherit;
    color: inherit;
    text-align: inherit;
    vertical-align: baseline;
}

body {
    background-color: var(--c-bg);
    background-size: cover;
    background-position: center;
    height: 100vh;
    overflow: hidden;
    font-family: var(--font-mono);
    color: var(--text);
}

/* --- LOGIN BUTTON --- */
.login-trigger {
    position: fixed; top: 20px; left: 20px; z-index: 2000;
    background: rgba(var(--void-rgb), 0.8); border: 1px solid var(--c-red); color: var(--c-red);
    padding: 8px 15px; font-family: var(--font-ui); letter-spacing: 1px; cursor: pointer;
    transition: 0.3s;
    clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px);
}
/* Classification red is one of the three things allowed to glow (depth.css
   rule 3) and this is a hover, which is feedback rather than resting state.
   It keeps its bloom; the bloom is simply the token's red now. */
.login-trigger:hover { background: var(--c-red); color: #000; box-shadow: 0 0 15px var(--c-red); }

/* --- LOGIN MODAL --- */
.modal-overlay {
    position: fixed; inset: 0; background: rgba(var(--void-rgb), 0.95);
    z-index: 3000; display: none; align-items: center; justify-content: center;
    /* The -webkit- prefix was missing and Safari is the browser that still needs
       it, so on Safari this scrim has never blurred. One line, and the modal
       reads the same everywhere. A full-screen blur is within the glass budget:
       it is bounded, it is elevated, and there is exactly one of it. */
    -webkit-backdrop-filter: blur(5px);
    backdrop-filter: blur(5px);
}
.modal-overlay.active { display: flex; }
/*
 * `width: 350px` was a FIXED width on the one box every member has to use. The modal
 * is centred by flex, so on any viewport narrower than 350px — a 320px phone, or a
 * 360px one in a split view — the sign-in form ran off both edges and the password
 * field could not be fully seen. `* { box-sizing: border-box }` above means the 30px
 * padding is already inside the 350, so the width alone was the overflow.
 *
 * min() keeps the intended 350px wherever there is room for it and lets the box shrink
 * below that where there is not, leaving a 16px gutter each side. No breakpoint: this
 * is not a layout change at a size, it is a ceiling.
 *
 * ELEVATION: this box is a sheet over the page, which is e3 — and it already carries
 * the whole of that elevation without borrowing a shadow. The red halo IS its cast
 * light, the 0.95 scrim behind it is what a cast shadow would have been trying to
 * say, and its top edge is 5px of hazard stripe, so a lit edge would be painted
 * underneath the one thing that covers it. Adding --shadow-e3 here would be a black
 * shadow on a black scrim: four properties on paper, none of them visible. Left
 * alone deliberately, which is not the same as overlooked.
 */
.login-box {
    border: 2px solid var(--c-red);
    padding: 30px; width: min(350px, calc(100vw - 32px)); background: var(--void);
    box-shadow: 0 0 50px var(--c-red-dim);
    text-align: center; position: relative;
}
.login-box::before {
    content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 5px;
    background: repeating-linear-gradient(45deg, var(--c-red), var(--c-red) 10px, var(--void) 10px, var(--void) 20px);
}
.login-input {
    width: 100%; background: var(--pane-2-solid); border: 1px solid var(--c-line-2);
    color: var(--c-yellow); padding: 12px; margin-bottom: 15px;
    font-family: var(--font-mono);   /* `outline: none` deleted -- see FOCUS below */
}
.login-input:focus { border-color: var(--c-yellow); }
.login-btn {
    width: 100%; background: var(--c-red); border: none; padding: 10px;
    font-family: var(--font-ui); font-size: 1.5rem; cursor: pointer;
    clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px);
}
.login-btn:hover { background: var(--c-yellow); color: #000; }

/* --- LAYER 1: CANVAS EMBERS --- */
#ember-canvas {
    position: fixed; inset: 0; z-index: 1; pointer-events: none;
}

/* --- LAYER 2: THERMAL FLASHLIGHT --- */
.thermal-layer {
    position: fixed; inset: 0;
    background: rgba(var(--void-rgb), 0.9);
    z-index: 2; pointer-events: none;
    mask-image: radial-gradient(circle 300px at var(--cursor-x) var(--cursor-y), black 0%, transparent 100%);
    -webkit-mask-image: radial-gradient(circle 300px at var(--cursor-x) var(--cursor-y), black 0%, transparent 100%);
    mask-composite: exclude;
}

/* --- LAYER 3: SCANLINES ---
   Left exactly as it is. This page's film is coarser than the one depth.css
   paints on the member surfaces (2px at 4px here, 1px at 4px there) and that
   is the difference between a splash screen and a workstation. Swapping it
   would be the single most noticeable thing anybody could do to this page. */
.scanlines {
    position: fixed; inset: 0;
    background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.1) 50%);
    background-size: 100% 4px; pointer-events: none; z-index: 3; opacity: 0.5;
}

/* --- LAYER 4: UI CONTAINER --- */
.container {
    position: relative; z-index: 10; height: 100vh;
    display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 20px;
}

/* --- THE TACTICAL HUD BOX ---
 *
 * ELEVATION, AND THE DECLARATION THAT HAD NEVER RENDERED.
 *
 * `box-shadow: 0 0 80px rgba(0,0,0,0.8)` stood here: an omnidirectional halo,
 * which is light from nowhere and the exact thing depth.css rule 1 exists to
 * refuse -- and it was INVISIBLE anyway, because clip-path clips an element's
 * box-shadow along with the element. This box has had a shadow declared and no
 * shadow drawn for as long as it has had its cut corner.
 *
 * filter: drop-shadow() is the one form that follows a clipped silhouette, so
 * the shadow now falls DOWN and AWAY, around the bevel, the way the rest of the
 * site's panels do. It is deliberately UNDER-cooked: --shadow-e2 pulls itself in
 * with a -24px spread and drop-shadow() has no spread to pull with, so the alpha
 * and the blur are dialled back instead until it lands in the same place. Depth
 * you NOTICE is depth done wrong; what you should notice is that the box has a
 * thickness, not that something has appeared beneath it.
 *
 * No backdrop-filter, and that is not an oversight -- see the header. The embers
 * and the thermal layer are meant to be seen through this panel, sharp.
 *
 * (The filter creates a containing block for fixed descendants. There are none
 * inside .content-box: every child here is static or relative.)
 */
.content-box {
    background: var(--c-panel);
    clip-path: polygon(0 0, 100% 0, 100% calc(100% - 30px), calc(100% - 30px) 100%, 0 100%);
    border-left: 4px solid var(--c-red);
    max-width: 600px; width: 100%; text-align: center;
    filter: drop-shadow(0 16px 30px rgba(0, 0, 0, 0.55));
    position: relative;
}

.hazard-bar {
    height: 12px; width: 100%;
    background: repeating-linear-gradient(45deg, var(--c-red), var(--c-red) 10px, var(--void) 10px, var(--void) 20px);
    opacity: 0.9;
}

.inner-padding { padding: 2.5rem 3rem; }

h1 {
    font-family: var(--font-display); font-size: 5rem;
    color: var(--c-red); line-height: 0.8; margin-bottom: 5px; text-shadow: 3px 3px 0 #000;
}

.tagline {
    font-family: var(--font-ui); font-size: 1.5rem; color: var(--text-2);
    margin-bottom: 2rem; letter-spacing: 3px; text-transform: uppercase;
    border-bottom: 1px solid var(--c-line); display: inline-block; padding-bottom: 5px;
}

.victim-counter {
    font-size: 0.75rem; color: var(--c-yellow); letter-spacing: 1px; margin-bottom: 25px;
    border: 1px dashed var(--c-line); display: inline-block; padding: 5px 10px; background: var(--void);
}
.victim-counter span { color: #fff; font-weight: bold; }

/* --- ROULETTE HUD ---
 *
 * ELEVATION. This is the one panel on the page with a plain rectangular border,
 * no clip-path and nothing covering its top edge, so it is the one that can take
 * the treatment whole: a top edge that catches the light (the red border warms
 * toward the classification ink at the top and stays at --c-red-dim everywhere
 * else), a specular 1px inside it, and a shadow that falls BELOW. Four properties
 * moving together, which is depth.css rule 2, on a panel that previously had a
 * flat 1px box around a flat fill.
 *
 * The corner brackets are untouched. They are the motif and they are why this
 * panel is not simply a .pane.
 */
.roulette-box {
    background: rgba(20, 0, 0, 0.5); border: 1px solid var(--c-red-dim);
    border-top-color: rgba(var(--classify-rgb), 0.4);
    padding: 15px; margin: 0 auto 25px auto; position: relative;
    box-shadow: inset 0 1px 0 var(--gloss-e1), var(--shadow-e1);
}
.roulette-box::before {
    content: ''; position: absolute; top: -1px; left: -1px; width: 8px; height: 8px;
    border-top: 2px solid var(--c-red); border-left: 2px solid var(--c-red);
}
.roulette-box::after {
    content: ''; position: absolute; bottom: -1px; right: -1px; width: 8px; height: 8px;
    border-bottom: 2px solid var(--c-red); border-right: 2px solid var(--c-red);
}
/*
 * THE ROULETTE READOUT'S GLOW WAS THE RETIRED BRAND RED, hiding from the token
 * wave as an rgb triple: rgba(255, 42, 0, .4) is #ff2a00, the hex this site
 * moved off when --c-red became the classification ink. Every other red on this
 * page moved with the token; this one could not, because a text-shadow cannot
 * take a var() colour, and so the one bloom on the landing page has been the
 * only orange-red left on the site. Composed from --classify-rgb now, which is
 * the same mechanism depth.css uses everywhere else.
 */
.roulette-display {
    font-family: var(--font-ui); font-size: 1.3rem; color: #fff;
    min-height: 1.3em; margin-bottom: 10px; text-shadow: 0 0 10px rgba(var(--classify-rgb), 0.4);
}
/* --text-3, not --text-dim. #888 measures 5.6:1 here and --text-3 is 5.9;
   --text-dim is 7.1 and would have brightened this control by a visible
   stop and a half. The ramp has five steps so that a substitution can be
   chosen rather than rounded. */
.btn-roulette {
    background: transparent; border: 1px solid var(--c-line-2); color: var(--text-3);
    padding: 5px 12px; font-size: 0.8rem; cursor: pointer;
    font-family: var(--font-mono); text-transform: uppercase; transition: 0.3s;
}
.btn-roulette:hover { border-color: var(--c-yellow); color: var(--c-yellow); background: rgba(255, 204, 0, 0.1); }

/* --- FORM ---
 *
 * ELEVATION, INVERTED. An input trough is the one surface on a page that is
 * BELOW the plane rather than above it, and light from above says so by darkening
 * its top edge instead of lighting it: --c-line-3 on top, --c-line everywhere
 * else. It is a two-value difference and you will never consciously see it; what
 * you will see is that the field reads as a slot cut into the panel rather than
 * as a rectangle drawn on it.
 */
.input-group {
    display: flex; background: var(--void); border: 1px solid var(--c-line);
    border-top-color: var(--c-line-3); padding: 4px;
}

input[type="email"] {
    flex: 1; background: transparent; border: none; padding: 15px;
    color: #fff; font-family: var(--font-mono); font-size: 1rem;
    /* `outline: none` deleted -- see FOCUS below */
}

button.btn-ignite {
    background: var(--c-red); border: none; color: #000; padding: 0 25px;
    font-family: var(--font-ui); font-size: 1.4rem; cursor: pointer;
    transition: 0.2s; clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px);
    opacity: 0.4; pointer-events: none;
}
button.btn-ignite.ready { opacity: 1; pointer-events: auto; }
button.btn-ignite:hover { background: var(--c-yellow); box-shadow: 0 0 25px var(--c-red); }

.waiver-box {
    margin-top: 15px; display: flex; align-items: flex-start; gap: 10px; text-align: left;
}
/* #666 measured 3.5:1 on this panel -- below AA, on the one paragraph on the
   page that is a legal disclaimer. --text-faint is 4.8:1 and is the faintest
   colour tokens.css is willing to name for text, which is the whole reason it
   is the faintest colour available to substitute here. */
.waiver-box label { font-size: 0.65rem; color: var(--text-faint); line-height: 1.3; cursor: pointer; }
.waiver-box label:hover { color: var(--text-dim); }
input[type="checkbox"] { accent-color: var(--c-red); margin-top: 3px; cursor: pointer; }

.status-msg { margin-top: 15px; font-weight: bold; font-size: 0.8rem; height: 20px; }

/* --- TICKER ---
   Bottom-fixed, so its TOP edge is the one facing the light and it already has
   the brightest thing on the page sitting on it: a 2px classification rule. It
   gets no shadow. A shadow above a bottom bar is light from below, which is
   depth.css rule 1 read backwards. */
.ticker-wrap {
    position: fixed; bottom: 0; left: 0; width: 100%;
    background: var(--void); color: var(--c-red); border-top: 2px solid var(--c-red);
    padding: 8px 0; z-index: 50; font-size: 0.8rem; text-transform: uppercase; white-space: nowrap; overflow: hidden;
}
.ticker-move { display: inline-block; padding-left: 100%; animation: ticker 120s linear infinite; }
.ticker-item { display: inline-block; padding: 0 60px; }
.ticker-item span { color: #fff; margin: 0 5px; }
@keyframes ticker { 0% { transform: translate3d(0, 0, 0); } 100% { transform: translate3d(-100%, 0, 0); } }

/* --- EXTRAS ---
 *
 * The two corner controls. `border: 1px solid rgba(255,255,255,.2)` was a
 * NEUTRAL white hairline, which on a blue-black ground is the same mistake
 * depth.css section 1 corrects on .dash-nav: a neutral edge on a cool ground
 * reads as a dirty line, and any glow crossing it changes hue halfway.
 *
 * --edge-e2 is the same 0.20 alpha it already had, in the right family, so the
 * weight of the box does not move; --edge-e3 on the top edge is the lit edge,
 * which is the whole of the elevation these two get and is worth about three
 * units of brightness on one hairline.
 *
 * The ink was rgba(255,255,255,.4) -- about #666 once composited, i.e. the same
 * failing contrast the waiver text had, on the link that is the public
 * archive's only door.
 */
.emergency-btn {
    position: fixed; top: 20px; right: 20px;
    border: 1px solid var(--edge-e2); border-top-color: var(--edge-e3);
    color: var(--text-faint);
    padding: 8px 12px; text-decoration: none; font-size: 0.7rem; z-index: 100;
    transition: 0.3s;
}
.emergency-btn:hover { border-color: #fff; color: #fff; background: rgba(var(--void-rgb), 0.8); }

/*
 * [ BROWSE DECLASSIFIED RATIONS ] — the ONE thing WS-G added to the landing page.
 *
 * FIXED POSITIONING IS NOT A STYLE CHOICE, IT IS THE WHOLE REASON THIS RULE EXISTS.
 *
 * This page sets `body { height: 100vh; overflow: hidden }` and lays the splash out
 * against that viewport: the ember canvas, the thermal layer, the scanlines, the
 * centred HUD box and the ticker are all positioned against it. Anything added in
 * NORMAL FLOW pushes that layout around and risks reflowing the one page the owner
 * asked not to lose. Taken out of flow, this link cannot move a pixel of it.
 *
 * It carries .emergency-btn as well as this class, so it inherits that control's
 * border, colour, padding, size, layer and transition and this rule is three
 * declarations rather than a second button. Top-LEFT because .emergency-btn holds
 * top-right and the PANIC BUTTON was there first; the newer control moves.
 *
 * Below 600px the two would collide, so this one drops to the bottom-left, where
 * nothing else on the page is drawn.
 */
.browse-btn { top: 20px; left: 20px; right: auto; }

@media (max-width: 600px) {
    .browse-btn { top: auto; bottom: 20px; left: 20px; }
}

.idle-overlay {
    position: fixed; inset: 0; background: rgba(15, 0, 0, 0.98); z-index: 999;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    opacity: 0; pointer-events: none; transition: 0.5s;
}
.idle-overlay.active { opacity: 1; pointer-events: auto; }
/* The one blackout on the site that is deliberately NOT the ground. SYSTEM
   FAILURE is supposed to arrive in a red-black room, and re-pointing this at
   --void would be the difference between an alarm and a screensaver. Left as
   it is, on purpose. */
.idle-text { font-family: var(--font-display); font-size: 4rem; color: var(--c-red); animation: pulse 0.8s infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }

@media (max-width: 600px) {
    h1 { font-size: 3.5rem; }
    .content-box { margin: 10px; max-width: 95%; }
    .inner-padding { padding: 1.5rem; }
    .input-group { flex-direction: column; background: transparent; border: none; gap: 10px; }
    input[type="email"] { background: var(--void); border: 1px solid var(--c-line); }
}

.toggle-link { display: block; margin-top: 15px; font-size: 0.8rem; color: var(--text-faint); cursor: pointer; }
.toggle-link:hover { color: #fff; }

/* [ ABORT SEQUENCE ]. Was an inline style on a <span onclick>; the declarations are
   unchanged, they just live in a class now so the <button> can share the reset.
 *
 * #444 IS LEFT AS A LITERAL AND IT IS THE ONLY GREY ON THIS PAGE THAT IS. The ink
 * ramp starts at --text-faint (4.8:1) because tokens.css refuses to name a text
 * colour below AA, and this control is deliberately two stops under that: the
 * escape hatch on a modal that calls itself SECURITY CLEARANCE is supposed to be
 * something you have to look for. Re-pointing it at the faintest legal token would
 * brighten it by six stops, which is the one change on this page a person who knows
 * it would notice immediately. Keyboard users are not affected -- the focus ring
 * below is a 2px yellow outline and does not care what the resting colour is -- and
 * the hover, which is the affordance that actually matters, is on the ramp. */
.abort-link { font-size: 0.7rem; color: #444; cursor: pointer; }
.abort-link:hover { color: var(--text-3); }

/* ====================================================================
   FOCUS

   There were two `outline: none` declarations in this file and zero
   :focus-visible rules, so nothing on this page showed a keyboard user
   where they were. Yellow is already the interactive accent, so the
   ring is on-theme by construction.

   IT STAYS YELLOW, and that is a decision rather than an omission. The
   rest of the site focuses in --chrome, because --chrome is the colour
   of the machine on a surface whose whole palette is blue. This page's
   palette is red, yellow and black; a blue ring on it would be the one
   thing a returning visitor could point at and name, and
   025_theme_contract_test.php pins the inset ring's colour besides. What
   the ring borrows from the site is its CONSTRUCTION, which it already
   had: 2px, offset, and a box-shadow wherever an outline cannot survive.

   THE NON-OBVIOUS PART: all three buttons on this page -- .login-trigger,
   .login-btn and .btn-ignite -- carry a clip-path, and clip-path clips
   the outline too. A plain `outline` on any of them is drawn and then
   immediately clipped away, i.e. invisible. They get an inset ring
   instead. Anything in this file that grows a clip-path has to be added
   to that second selector list or its focus state silently disappears.

   Note what is deliberately NOT in that rule: `outline: none`. It would be
   redundant -- the outline on these three is already clipped out of
   existence -- and it would put back the exact declaration this section
   exists to delete. If one of them ever loses its clip-path it degrades to
   two focus rings, which is ugly and obvious, rather than to none, which is
   silent.

   :focus-visible, not :focus, so a mouse click does not paint a ring
   around the button somebody just clicked.
   ==================================================================== */
:focus-visible {
    outline: 2px solid var(--c-yellow);
    outline-offset: 2px;
}
.login-trigger:focus-visible,
.login-btn:focus-visible,
.btn-ignite:focus-visible {
    box-shadow: inset 0 0 0 2px var(--c-yellow);
}

/* ====================================================================
   MOTION

   This page ran an unconditional 100-particle requestAnimationFrame
   ember loop, a 120-second infinite ticker, a 0.8s infinite pulse and
   five transitions, with no prefers-reduced-motion guard anywhere.

   The CSS half is below. The rAF loop cannot be stopped from CSS, so
   public/js/landing.js checks the same media query and draws one static
   ember frame instead of starting the loop. The page keeps its look and
   loses the motion.

   The ticker and the idle pulse are named explicitly because
   `animation-duration: .01ms` on an infinite animation still leaves it
   running -- it just runs absurdly fast.

   NOTHING ADDED IN THE HARMONISATION PASS MOVES. The elevation the three
   panels gained is a border colour, an inset highlight and a static
   shadow; the drop-shadow on the HUD box is a filter, not a transition.
   There is nothing new here for this block to catch, which is the state
   a reduced-motion guard should be left in.
   ==================================================================== */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    .ticker-move { animation: none; }
    .idle-text   { animation: none; }
}
