@font-face{font-family:"PlexC";src:url(/fonts/plexcond-600.woff2) format("woff2");font-weight:600;font-display:swap}
@font-face{font-family:"PlexC";src:url(/fonts/plexcond-700.woff2) format("woff2");font-weight:700;font-display:swap}
@font-face{font-family:"Plex";src:url(/fonts/plexsans-400.woff2) format("woff2");font-weight:400;font-display:swap}
@font-face{font-family:"Plex";src:url(/fonts/plexsans-600.woff2) format("woff2");font-weight:600;font-display:swap}
@font-face{font-family:"Mono";src:url(/fonts/mono-400.woff2) format("woff2");font-weight:400;font-display:swap}
@font-face{font-family:"Mono";src:url(/fonts/mono-500.woff2) format("woff2");font-weight:500;font-display:swap}

/* ============================================================================
   Nux — /demo. The phone simulator.

   One large phone holding a full scripted session, switchable between Telegram
   and LINE, driven by a command rail. It replaced a five-act scroll film on
   2026-09-08: the film was read as documentation rather than watched as a
   film, so the page became something you operate instead.

   Two rules carried over from the rest of the site:

   · EVERY LINE-HEIGHT IS NUMERIC. `line-height: normal` is computed from the
     active font's metrics, so a font swap resizes every box and shoves the
     layout (gotcha #64). Buttons need it stated explicitly — they do not
     inherit it from body.
   · NO INLINE STYLE, EVER. The CSP has no `unsafe-inline`; demo.js mutates
     presentation through CSSOM property setters only (gotcha #61).
   ========================================================================= */

/* --------------------------------------------------------------- tokens -- */
:root{
  --ground:#0A0B0D;
  --raised:#101216;
  --sunk:#15181D;
  --ink:#EDEEF0;
  --ink-soft:#9BA1AB;
  --ink-faint:#7B818C;

  /* The accent means DEVIATION. Nothing healthy is ever this colour. */
  --accent:#FF6B2C;
  --accent-soft:#2A1710;
  --accent-ink:#0A0B0D;

  --line:rgba(255,255,255,.11);
  --line-strong:rgba(255,255,255,.19);

  --sh:220 40% 2%;
  --e1:0 1px 2px hsl(var(--sh)/.06), 0 1px 3px hsl(var(--sh)/.05);
  --e2:0 1px 2px hsl(var(--sh)/.05), 0 6px 16px -4px hsl(var(--sh)/.12);
  --e3:0 2px 4px hsl(var(--sh)/.05), 0 16px 34px -8px hsl(var(--sh)/.16),
       0 40px 70px -30px hsl(var(--sh)/.14);

  --r1:7px; --r2:11px; --r3:17px; --r4:24px;
  --s1:.25rem; --s2:.5rem;  --s3:.75rem; --s4:1rem;   --s5:1.5rem;
  --s6:2rem;   --s7:3rem;   --s8:4rem;

  --gutter:clamp(1rem,4.5vw,2.5rem);
  --rail-w:250px;
  --ctx-w:290px;

  --font:"Plex",system-ui,sans-serif;
  --cond:"PlexC","Plex",system-ui,sans-serif;
  --mono:"Mono",ui-monospace,monospace;

  --ease:cubic-bezier(.23,1,.32,1);
  --ease-soft:cubic-bezier(.4,0,.2,1);

  /* --- Telegram skin. Follows the page theme, exactly as the homepage
         mockups do, so the two pages never disagree about the product. --- */
  --tg-bg:#0E1319; --tg-bar:#161D26; --tg-in:#1B242F; --tg-out:#2A4257;
  --tg-ink:#E8ECF1; --tg-soft:#8D9AA8;

  /* --- LINE skin. A fixed palette, not theme-derived: LINE's wallpaper is
         the app's own, and it stays light inside a dark page. Only the
         wallpaper shifts with the theme, matching the homepage. --- */
  --l-bg:#8FA9C4; --l-bar:#F4F6F8; --l-in:#FFFFFF; --l-out:#8DE05A;
  --l-ink:#1A1D21; --l-soft:#575F6C; --l-green:#06C755;
}

html[data-theme="light"]{
  --ground:#FFFFFF; --raised:#FAFAFA; --sunk:#F2F3F5;
  --ink:#0C0E11; --ink-soft:#4E545E; --ink-faint:#5F656D;
  --accent:#B83C08; --accent-soft:#FDF1EE; --accent-ink:#FFFFFF;
  --line:rgba(12,14,17,.11); --line-strong:rgba(12,14,17,.19);
  --sh:38 12% 32%;

  --tg-bg:#EEF2F6; --tg-bar:#FFFFFF; --tg-in:#FFFFFF; --tg-out:#D6E7F7;
  --tg-ink:#12171D; --tg-soft:#5E6873;
  --l-bg:#A9C0D8;
}

/* ----------------------------------------------------------------- base -- */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{background:var(--ground);color-scheme:dark}
html[data-theme="light"]{color-scheme:light}
body{
  background:var(--ground);color:var(--ink);
  font-family:var(--font);font-size:16px;line-height:1.55;font-weight:400;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;font-variant-numeric:tabular-nums;font-optical-sizing:auto;
}
::selection{background:var(--accent);color:var(--accent-ink)}
:root{caret-color:var(--accent);accent-color:var(--accent)}
:where(a,button,[tabindex]):focus-visible{
  outline:2px solid var(--accent);outline-offset:3px;border-radius:var(--r1)
}
@supports(scrollbar-width:thin){html{scrollbar-color:var(--line-strong) transparent;scrollbar-width:thin}}
a{color:inherit;text-underline-offset:.18em;text-decoration-thickness:.07em}
button{font:inherit;line-height:1.4;color:inherit}
.u-hide{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.mark{flex:none}
.wm{font-family:var(--cond);font-weight:700;letter-spacing:-.01em;line-height:1.2;font-size:1.0625rem}

/* =============================================================== layout == */
.lab{display:grid;grid-template-columns:1fr;min-height:100svh}

@media (min-width:1240px){
  .lab{grid-template-columns:var(--rail-w) 1fr var(--ctx-w)}
}
@media (min-width:940px) and (max-width:1239px){
  .lab{grid-template-columns:var(--rail-w) 1fr}
}

/* ================================================================= rail == */
.rail{display:none}
@media (min-width:940px){
  .rail{
    display:flex;flex-direction:column;gap:var(--s4);
    position:sticky;top:0;height:100svh;padding:var(--s5) var(--s4);
    border-right:1px solid var(--line);background:var(--ground);z-index:20;
  }
}
.rail__brand{display:flex;align-items:center;gap:9px;text-decoration:none;color:inherit}
.rail__acct{
  border:1px solid var(--line);border-radius:var(--r2);padding:var(--s3);
  background:var(--raised);box-shadow:var(--e1)
}
.rail__acctname{font-weight:600;font-size:.875rem;line-height:1.3;letter-spacing:-.01em}
.rail__state{
  display:flex;align-items:center;gap:6px;margin-top:5px;
  font-family:var(--mono);font-size:.6875rem;line-height:1.5;color:var(--ink-soft)
}
.dot{width:6px;height:6px;border-radius:50%;background:#1B9E5A;flex:none}
.dot--live{animation:pulse 2.6s var(--ease-soft) infinite}
@keyframes pulse{
  0%{box-shadow:0 0 0 0 rgba(27,158,90,.45)}
  70%{box-shadow:0 0 0 7px rgba(27,158,90,0)}
  100%{box-shadow:0 0 0 0 rgba(27,158,90,0)}
}

.rail__list{display:flex;flex-direction:column;flex:1;min-height:0}
.rail__cmds{
  display:flex;flex-direction:column;gap:1px;overflow-y:auto;flex:1;min-height:0;
  /* an overflow:auto region with no visible scrollbar is an invisible scroll
     region (gotcha #62a) — `local` layers mask the shadow at the ends */
  background:
    linear-gradient(var(--ground) 34%, rgba(0,0,0,0)) top    /100% 22px no-repeat local,
    linear-gradient(rgba(0,0,0,0), var(--ground) 66%) bottom /100% 22px no-repeat local,
    radial-gradient(farthest-side at 50% 0,   rgba(0,0,0,.30), rgba(0,0,0,0)) top    /100% 9px no-repeat scroll,
    radial-gradient(farthest-side at 50% 100%,rgba(0,0,0,.30), rgba(0,0,0,0)) bottom /100% 9px no-repeat scroll;
}
.rail__group{
  font-family:var(--mono);font-size:.625rem;line-height:1.6;letter-spacing:.13em;
  text-transform:uppercase;color:var(--ink-faint);
  padding:var(--s3) 8px 5px;position:sticky;top:0;background:var(--ground);z-index:1
}
.rail__group:first-child{padding-top:0}
.rail__cmd{
  display:flex;justify-content:space-between;align-items:baseline;gap:var(--s3);
  font-family:var(--mono);font-size:.75rem;line-height:1.5;color:var(--ink-soft);
  padding:5px 8px;border-radius:var(--r1);border:0;background:none;cursor:pointer;
  text-align:left;width:100%;transition:background 140ms var(--ease),color 140ms var(--ease)
}
.rail__cmd em{
  font-style:normal;color:var(--ink-faint);font-size:.6875rem;line-height:1.5;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:0 1 auto;text-align:right
}
.rail__cmd>span:first-child{flex:none}
@media (hover:hover) and (pointer:fine){.rail__cmd:hover{background:var(--sunk);color:var(--ink)}}
.rail__cmd:active{transform:translateY(1px)}
.rail__cmd[aria-current="true"]{background:var(--sunk);color:var(--ink);font-weight:500}
.rail__foot{
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);font-size:.75rem;line-height:1.6;
  color:var(--ink-faint);padding-top:var(--s4);border-top:1px solid var(--line)
}
.rail__foot a{text-decoration:none}

/* ================================================================ stage == */
.stage{display:flex;flex-direction:column;align-items:center;min-width:0}

.top{
  position:sticky;top:0;z-index:30;width:100%;
  display:flex;align-items:center;gap:var(--s3);
  padding:var(--s3) var(--gutter);
  background:color-mix(in srgb, var(--ground) 88%, transparent);
  backdrop-filter:blur(10px);border-bottom:1px solid var(--line);
}
.top__brand{display:flex;align-items:center;gap:8px;text-decoration:none;color:inherit}
@media (min-width:940px){.top__brand{display:none}}
.top__sp{flex:1}

/* --- the platform switch --- */
.seg{
  display:flex;gap:2px;padding:3px;border:1px solid var(--line);
  border-radius:999px;background:var(--raised)
}
.seg__b{
  display:inline-flex;align-items:center;gap:6px;
  padding:6px 14px;border:0;border-radius:999px;background:none;cursor:pointer;
  font-family:var(--mono);font-size:.6875rem;line-height:1.5;letter-spacing:.04em;
  text-transform:uppercase;color:var(--ink-faint);
  transition:background 160ms var(--ease),color 160ms var(--ease)
}
.seg__b[aria-selected="true"]{background:var(--accent);color:var(--accent-ink);font-weight:600}
@media (hover:hover) and (pointer:fine){
  .seg__b:not([aria-selected="true"]):hover{color:var(--ink)}
}

.tt{
  display:inline-flex;align-items:center;gap:7px;padding:6px 11px;
  border:1px solid var(--line);border-radius:999px;background:none;cursor:pointer;
  font-family:var(--mono);font-size:.6875rem;line-height:1.5;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-soft)
}
.tt__d{
  width:11px;height:11px;border-radius:50%;flex:none;
  background:linear-gradient(90deg,var(--ink) 50%, transparent 50%);
  border:1.5px solid var(--ink);box-sizing:border-box
}
@media (max-width:400px){.tt__l{display:none}}

.sheet__open{
  display:inline-flex;align-items:center;gap:7px;padding:6px 12px;
  border:1px solid var(--line);border-radius:999px;background:none;cursor:pointer;
  font-family:var(--mono);font-size:.6875rem;line-height:1.5;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-soft)
}
@media (min-width:940px){.sheet__open{display:none}}

/* ================================================================ phone == */
.frame{
  display:flex;flex-direction:column;align-items:center;gap:var(--s3);
  padding:var(--s3) var(--gutter) 0;width:100%;
}
.phone{
  /* Locked to a real modern phone. iPhone 15/16 Pro is 393x852pt, Galaxy S24
     360x780, Pixel 8 412x915 — all ~2.167. The Dynamic Island and the 44px
     corner radii only exist on phones of that ratio, so drawing them on a
     1.76 body was a mismatch you could feel without being able to name it.

     HEIGHT LEADS AND WIDTH FOLLOWS, because vertical space is the scarce
     resource on a laptop: at a 900px viewport the phone is 339px wide, at
     1080px it becomes a true 393x852, and the cap stops it turning into a
     tablet on a large monitor. You cannot have both the right ratio and a
     393px reading width below ~1080px of viewport — one of them has to give,
     and the ratio is the one that shows. */
  --ar:2.167;
  /* The bezel is NOT part of the display. .phone__body carries 9px of padding
     and a 2px border per side, so the screen is 22px narrower than the phone;
     dividing the outer width by the ratio produced a 2.32 screen. Size the
     screen, then add the shell back. */
  --bezel:11px;
  /* Width is clamped and height follows it, rather than the reverse: driving
     width from viewport height alone collapsed the phone to 234px at a 720px
     viewport — narrower than the thread can be read at. The floor wins on a
     short screen and the page scrolls a little instead. */
  --screen-w:clamp(300px, calc((100svh - 165px) / var(--ar)), 400px);
  --screen-h:calc(var(--screen-w) * var(--ar));
  width:calc(var(--screen-w) + var(--bezel) * 2);max-width:100%;position:relative
}
.phone__body{
  position:relative;border:2px solid var(--ink);border-radius:44px;padding:9px;
  background:var(--ground);box-shadow:var(--e3)
}
.phone__island{
  position:absolute;top:21px;left:50%;transform:translateX(-50%);
  width:88px;height:24px;border-radius:14px;background:var(--ink);z-index:6
}
.phone__screen{
  position:relative;border-radius:34px;overflow:hidden;
  height:var(--screen-h);display:flex;flex-direction:column
}

/* ---- the app's own chrome, inside the screen ---- */
.app__bar{
  flex:none;display:flex;align-items:center;gap:10px;
  padding:34px 14px 11px;position:relative;z-index:4
}
.app__av{width:30px;height:30px;border-radius:50%;display:grid;place-items:center;flex:none}
.app__nm{font-size:.8125rem;line-height:1.25;font-weight:600}
.app__st{font-family:var(--mono);font-size:.6875rem;line-height:1.4;display:block}

.app__thread{
  flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  padding:12px 12px 18px;display:flex;flex-direction:column;gap:9px;
  scroll-behavior:smooth
}
@media (prefers-reduced-motion:reduce){.app__thread{scroll-behavior:auto}}

.app__comp{
  flex:none;display:flex;align-items:center;gap:9px;padding:9px 12px 15px
}
.app__field{
  flex:1;height:30px;border-radius:15px;display:flex;align-items:center;padding:0 12px;
  font-family:var(--mono);font-size:.6875rem;line-height:1.4
}
.app__send{width:28px;height:28px;border-radius:50%;flex:none;display:grid;place-items:center}

/* ---- platform skins on the screen ---- */
.phone[data-plat="telegram"] .phone__screen{background:var(--tg-bg)}
.phone[data-plat="telegram"] .app__bar{background:var(--tg-bar);color:var(--tg-ink)}
.phone[data-plat="telegram"] .app__av{background:var(--accent)}
.phone[data-plat="telegram"] .app__st{color:var(--accent)}
.phone[data-plat="telegram"] .app__comp{background:var(--tg-bar)}
.phone[data-plat="telegram"] .app__field{background:var(--tg-in);color:var(--tg-soft)}
.phone[data-plat="telegram"] .app__send{background:var(--accent)}

.phone[data-plat="line"] .phone__screen{background:var(--l-bg)}
.phone[data-plat="line"] .app__bar{background:var(--l-bar);color:var(--l-ink);
  border-bottom:1px solid rgba(0,0,0,.08)}
.phone[data-plat="line"] .app__av{background:var(--l-green)}
.phone[data-plat="line"] .app__st{color:#0B6B2E}
.phone[data-plat="line"] .app__comp{background:var(--l-bar)}
.phone[data-plat="line"] .app__field{background:#E8EBEF;color:var(--l-soft)}
.phone[data-plat="line"] .app__send{background:var(--l-green)}

/* ================================================== messages · shared ==== */
.ex{display:flex;flex-direction:column;gap:7px;scroll-margin-top:14px;border-radius:14px}
.ex.is-hit{animation:hit 1500ms var(--ease-soft)}
@keyframes hit{
  0%{box-shadow:0 0 0 2px var(--accent), 0 0 0 6px rgba(255,107,44,.24)}
  70%{box-shadow:0 0 0 2px var(--accent), 0 0 0 6px rgba(255,107,44,.10)}
  100%{box-shadow:0 0 0 0 rgba(255,107,44,0), 0 0 0 0 rgba(255,107,44,0)}
}
@media (prefers-reduced-motion:reduce){.ex.is-hit{animation:none;outline:2px solid var(--accent);outline-offset:2px}}

.out{align-self:flex-end;max-width:86%;padding:8px 12px;border-radius:15px;
  border-bottom-right-radius:5px;font-size:.8125rem;line-height:1.45}
.in{align-self:flex-start;max-width:92%;min-width:0}

/* No opacity here. --tg-soft passes AA on its own; compositing it at 75%
   dropped it to 4.16:1, which no token-reading audit would ever notice. */
.stamp{font-family:var(--mono);font-size:.625rem;line-height:1.4;text-align:right;
  margin-top:5px}
.daymark{
  align-self:center;font-family:var(--mono);font-size:.625rem;line-height:1.5;
  padding:3px 11px;border-radius:999px;margin-block:4px
}

.phone[data-plat="telegram"] .out{background:var(--tg-out);color:var(--tg-ink);font-family:var(--mono)}
.phone[data-plat="telegram"] .daymark{background:rgba(0,0,0,.30);color:var(--tg-ink)}
html[data-theme="light"] .phone[data-plat="telegram"] .daymark{background:rgba(0,0,0,.10);color:var(--tg-ink)}

.phone[data-plat="line"] .out{background:var(--l-out);color:var(--l-ink)}
/* .34 leaves white at 4.13:1 over the LIGHT wallpaper. .46 clears AA on both
   wallpapers (6.73:1 dark, 5.42:1 light) — the darker theme was never the
   binding case, which is why sampling one theme is not a check. */
.phone[data-plat="line"] .daymark{background:rgba(0,0,0,.46);color:#FFFFFF}

/* ============================================ TELEGRAM · the text idiom ==
   bot/formatters.py emits MarkdownV2: an emoji-prefixed bold title, a heavy
   divider, then bold labels with backticked values. It is a text message with
   structure, and it should read like one — not like a card.
   ======================================================================== */
.tgm{
  background:var(--tg-in);color:var(--tg-ink);
  padding:9px 12px;border-radius:15px;border-bottom-left-radius:5px;
  font-size:.8125rem;line-height:1.5
}
.tgm--alert{border-left:2px solid var(--accent)}
.tgm__t{font-weight:600;font-size:.8125rem;line-height:1.4}
.tgm__rule{color:var(--tg-soft);font-family:var(--mono);font-size:.625rem;
  line-height:1.2;letter-spacing:-.08em;margin:2px 0 5px;overflow:hidden;white-space:nowrap}
.tgm__sub{font-family:var(--mono);font-size:.6875rem;line-height:1.45;color:var(--tg-soft)}
.tgm__sec{font-weight:600;font-size:.75rem;line-height:1.5;margin-top:7px;color:var(--tg-ink)}
.tgm__kv{display:grid;grid-template-columns:auto 1fr;gap:1px 8px;margin-top:4px}
.tgm__k{font-size:.75rem;line-height:1.5;font-weight:600;color:var(--tg-ink);white-space:nowrap}
.tgm__v{font-family:var(--mono);font-size:.75rem;line-height:1.5;color:var(--tg-ink)}
.tgm__d{color:var(--tg-soft);font-family:var(--font);font-size:.6875rem;margin-left:5px}
.tgm__d--bad{color:var(--accent);font-weight:600}
.tgm__p{font-size:.8125rem;line-height:1.5;margin-top:5px}
.tgm__foot{font-family:var(--mono);font-size:.625rem;line-height:1.5;color:var(--tg-soft);margin-top:7px}
.tgm__kb{display:flex;flex-wrap:wrap;gap:4px;margin-top:9px}
.tgm__key{
  flex:1 1 auto;text-align:center;padding:7px 11px;border-radius:8px;
  background:var(--tg-out);color:var(--tg-ink);
  font-size:.75rem;line-height:1.4;font-weight:500
}
.tgm__num{display:flex;gap:8px;margin-top:5px;font-size:.75rem;line-height:1.55}
.tgm__num b{font-weight:600;flex:none;font-family:var(--mono);color:var(--tg-soft)}

/* ================================================ LINE · the Flex idiom ==
   line/formatters.py emits FlexBubble/FlexCarousel: a bordered card of boxes
   with a header, kv body and footer, plus quick-reply chips under the message.
   Ranked lists become a swipeable carousel (gotcha #31).
   ======================================================================== */
.lnm{
  background:var(--l-in);color:var(--l-ink);border-radius:15px;
  border-bottom-left-radius:5px;overflow:hidden;box-shadow:0 1px 2px rgba(0,0,0,.14)
}
.lnm--alert{border-left:3px solid var(--accent)}
.lnm--plain{padding:9px 12px;font-size:.8125rem;line-height:1.5}
.lnm__head{padding:11px 13px 9px;border-bottom:1px solid rgba(0,0,0,.08)}
.lnm__eye{
  font-family:var(--mono);font-size:.5625rem;line-height:1.5;letter-spacing:.13em;
  text-transform:uppercase;color:var(--l-soft)
}
.lnm__t{font-size:.9375rem;line-height:1.25;font-weight:700;letter-spacing:-.015em;margin-top:2px}
.lnm__sub{font-family:var(--mono);font-size:.625rem;line-height:1.45;color:var(--l-soft);margin-top:3px}
.lnm__body{padding:4px 13px 10px}
.lnm__sec{
  font-family:var(--mono);font-size:.5625rem;line-height:1.5;letter-spacing:.13em;
  text-transform:uppercase;color:var(--l-soft);margin-top:9px;padding-bottom:3px;
  border-bottom:1px solid rgba(0,0,0,.07)
}
.lnm__row{display:flex;justify-content:space-between;align-items:baseline;gap:10px;padding:5px 0}
.lnm__k{font-size:.75rem;line-height:1.45;color:var(--l-soft);flex:none}
.lnm__v{font-family:var(--mono);font-size:.75rem;line-height:1.45;font-weight:500;text-align:right}
.lnm__d{font-family:var(--font);font-size:.625rem;color:var(--l-soft);margin-left:5px;font-weight:400}
.lnm__d--bad{color:#C2410C;font-weight:600}
.lnm__p{padding:10px 13px;font-size:.8125rem;line-height:1.5}
.lnm__foot{
  padding:8px 13px;background:#F3F5F7;border-top:1px solid rgba(0,0,0,.07);
  font-family:var(--mono);font-size:.625rem;line-height:1.5;color:var(--l-soft)
}
/* LINE's own client puts white on this green: 2.26:1. Keep the brand green —
   it is what makes the button read as LINE — and darken the ink instead, which
   is the same call the brand contract makes for text on the accent fill. */
.lnm__btn{
  display:block;margin:0 13px 12px;padding:9px;border-radius:8px;text-align:center;
  background:var(--l-green);color:#05291A;font-size:.75rem;line-height:1.4;font-weight:600
}

/* ---- quick replies. LINE draws these under the message, not inside it. ---- */
.quick{display:flex;gap:6px;overflow-x:auto;padding-bottom:2px;scrollbar-width:none}
.quick::-webkit-scrollbar{display:none}
.quick__c{
  flex:none;padding:5px 12px;border-radius:999px;background:rgba(255,255,255,.92);
  border:1px solid var(--l-green);color:#0B6B2E;
  font-family:var(--mono);font-size:.6875rem;line-height:1.5;white-space:nowrap
}

/* ---- the carousel. A clipping container, so it must advertise itself. ---- */
.car{
  display:flex;gap:8px;overflow-x:auto;padding-bottom:4px;
  scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none
}
.car::-webkit-scrollbar{display:none}
.car__b{flex:none;width:176px;scroll-snap-align:start}
.car__hint{
  display:flex;align-items:center;gap:5px;margin-top:5px;
  font-family:var(--mono);font-size:.5625rem;line-height:1.5;letter-spacing:.08em;
  text-transform:uppercase;color:#2C3540
}

/* ================================== the banner · B's signature move ====== */
/* Slides down over the phone's own status bar while you are reading somewhere
   else in the thread. The frame is what makes it legible: it is unmistakably a
   phone notification rather than a website popup. */
.banner{
  position:absolute;top:8px;left:8px;right:8px;z-index:8;
  border-radius:16px;padding:10px 12px;cursor:pointer;text-align:left;
  border:1px solid var(--line-strong);box-shadow:var(--e3);
  transform:translateY(-140%);opacity:0;
  transition:transform 620ms var(--ease),opacity 380ms var(--ease-soft)
}
.banner.is-in{transform:translateY(0);opacity:1}
.phone[data-plat="telegram"] .banner{background:rgba(32,41,51,.95);backdrop-filter:blur(18px);
  border-color:rgba(255,255,255,.16);color:var(--tg-ink)}
.phone[data-plat="line"] .banner{background:rgba(255,255,255,.98);backdrop-filter:blur(18px);
  border-color:rgba(0,0,0,.12);color:var(--l-ink)}
.banner__top{
  display:flex;align-items:center;gap:6px;
  font-family:var(--mono);font-size:.5625rem;line-height:1.5;letter-spacing:.13em;
  text-transform:uppercase;opacity:.8
}
.banner__now{margin-left:auto;letter-spacing:.06em}
.banner__t{display:block;font-size:.8125rem;line-height:1.3;font-weight:700;margin-top:4px}
.banner__b{display:block;font-size:.75rem;line-height:1.45;margin-top:2px;opacity:.88}
.banner__hot{color:var(--accent);font-weight:600}
.phone[data-plat="line"] .banner__hot{color:#C2410C}

@media (prefers-reduced-motion:reduce){
  .banner{transition:opacity 200ms linear;transform:none}
  .banner.is-in{transform:none}
}

/* ------------------------------------------------- under-phone caption -- */
/* one row beside the button, not three stacked — the height it used to take
   is height the phone now has */
.cap{
  display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;justify-content:center;
  font-family:var(--mono);font-size:.6875rem;line-height:1.6;color:var(--ink-faint);
  text-align:center;max-width:620px
}
.cap__b{
  border:1px solid var(--line);border-radius:999px;background:none;cursor:pointer;
  padding:5px 12px;font-family:var(--mono);font-size:.6875rem;line-height:1.5;
  color:var(--ink-soft)
}
@media (hover:hover) and (pointer:fine){.cap__b:hover{border-color:var(--line-strong);color:var(--ink)}}

/* ============================================================== context == */
.ctx{display:none}
@media (min-width:1240px){
  .ctx{
    display:flex;flex-direction:column;gap:var(--s4);
    position:sticky;top:0;height:100svh;overflow-y:auto;
    padding:var(--s5) var(--s4);border-left:1px solid var(--line);background:var(--ground)
  }
}
.ctx__label{
  font-family:var(--mono);font-size:.625rem;line-height:1.6;letter-spacing:.13em;
  text-transform:uppercase;color:var(--ink-faint)
}
.ctx__card{
  border:1px solid var(--line);border-radius:var(--r2);background:var(--raised);
  padding:var(--s4);box-shadow:var(--e1)
}
.ctx__cmd{font-family:var(--mono);font-size:.8125rem;line-height:1.4;color:var(--accent);font-weight:500}
.ctx__t{font-size:.9375rem;line-height:1.3;font-weight:600;letter-spacing:-.015em;margin-top:6px}
.ctx__p{font-size:.8125rem;line-height:1.55;color:var(--ink-soft);margin-top:8px}
.ctx__meta{
  display:flex;flex-direction:column;gap:5px;margin-top:var(--s3);padding-top:var(--s3);
  border-top:1px solid var(--line);
  font-family:var(--mono);font-size:.6875rem;line-height:1.5;color:var(--ink-faint)
}
.ctx__meta b{color:var(--ink-soft);font-weight:500}

/* ============================================================== the sheet =
   Below the desktop breakpoint the rail becomes a slide-up command sheet.
   ======================================================================== */
.sheet{
  position:fixed;inset:0;z-index:60;display:none;
  background:color-mix(in srgb, var(--ground) 72%, transparent)
}
.sheet[data-open="true"]{display:block}
.sheet__panel{
  position:absolute;left:0;right:0;bottom:0;max-height:82svh;overflow-y:auto;
  background:var(--raised);border-top:1px solid var(--line);
  border-radius:var(--r4) var(--r4) 0 0;padding:var(--s4) var(--s4) var(--s6);
  box-shadow:var(--e3)
}
.sheet__grab{width:38px;height:4px;border-radius:2px;background:var(--line-strong);
  margin:0 auto var(--s4)}
.sheet__close{
  position:absolute;top:var(--s3);right:var(--s4);border:0;background:none;cursor:pointer;
  font-family:var(--mono);font-size:.6875rem;line-height:1.5;color:var(--ink-soft);
  text-transform:uppercase;letter-spacing:.08em
}

/* ================================================================ footer == */
.foot{border-top:1px solid var(--line);padding:var(--s6) var(--gutter);width:100%}
.foot__in{max-width:900px;margin-inline:auto;display:flex;flex-direction:column;gap:var(--s3)}
.foot__links{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);font-size:.8125rem;line-height:1.6}
.foot__links a{text-decoration:none;color:var(--ink-soft)}
.foot__note{font-size:.75rem;line-height:1.6;color:var(--ink-faint);max-width:60ch}
/* the buttons were landing exactly on the footer's top border, with the
   footer's own rule cutting through them */
.go{display:flex;flex-wrap:wrap;gap:var(--s3);justify-content:center;
  margin:var(--s6) 0 var(--s7)}
.btn{
  display:inline-flex;align-items:center;gap:8px;padding:11px 19px;border-radius:999px;
  text-decoration:none;font-weight:600;font-size:.875rem;line-height:1.4
}
.btn--pri{background:var(--accent);color:var(--accent-ink)}
.btn--sec{border:1px solid var(--line-strong);color:var(--ink)}

/* ================================================================ mobile ==
   Below the desktop breakpoint the bezel and island come off and the thread
   goes full-bleed: the visitor's own phone becomes the phone. A phone drawn
   inside a phone is a worse lie than no phone at all.
   ======================================================================== */
@media (max-width:939px){
  .frame{padding:0;gap:0}
  .phone{--screen-w:100%;--screen-h:calc(100svh - 118px);width:100%}
  .phone__body{border:0;border-radius:0;padding:0;box-shadow:none;background:none}
  .phone__island{display:none}
  .phone__screen{border-radius:0}
  .app__bar{padding-top:12px}
  .in{max-width:76%}
  .out{max-width:74%}
  .car__b{width:200px}
  .cap{padding:var(--s4) var(--gutter);max-width:none}
  .banner{top:10px}
}

/* the thread's own scroll is the point on desktop; on mobile the page
   scrolls the thread, so let the container grow rather than trap the scroll */
@media (max-width:939px){
  .app__thread{overscroll-behavior:auto}
}

/* ================================================================= no-JS ==
   The thread is rendered by script. With scripting off the page would be an
   empty phone, so the static fallback carries the first exchange and the
   calls to action (gotcha #60c).
   ======================================================================== */
.nojs{display:none}
html:not(.js) .nojs{display:block;padding:var(--s5) var(--gutter);max-width:640px;margin-inline:auto}
html:not(.js) .frame,
html:not(.js) .seg,
html:not(.js) .sheet__open{display:none}

/* Timestamps sit under the bubble in both apps, but they sit on different
   grounds: Telegram's thread ink, LINE's wallpaper. */
.phone[data-plat="telegram"] .stamp{color:var(--tg-soft)}
/* LINE's own client puts these in white on the wallpaper, which measures
   2.42:1. Dark ink on the same ground is 5.06:1 and still reads as a label. */
.phone[data-plat="line"] .stamp{color:#2C3540}

/* ====================================== narrow header · two rows =========
   brand + platform switch + Commands + theme do not fit one row on a phone:
   69px over at 320px, and 33px over at 401px — just above the breakpoint that
   drops the theme toggle's word, which is exactly where these things hide.
   The site's own answer to this is to wrap the header to a second row
   (gotcha #59a), so do that: identity and controls on row one, the platform
   switch full-width on row two where it is easiest to hit anyway.
   ======================================================================== */
@media (max-width:520px){
  .top{flex-wrap:wrap;row-gap:var(--s2)}
  .top__brand{order:1}
  .top__sp{order:2}
  .sheet__open{order:3}
  .tt{order:4}
  .seg{order:5;flex-basis:100%;justify-content:center}
  /* the header is now two rows tall, so the screen must give that back */
  .phone{--screen-h:calc(100svh - 158px)}
}
