:root{
  --bg:#080808; --card:#121212; --line:#242424;
  --coral:#EA009A; --coral-dim:#B00074;
  --txt:#fff; --mut:#8a8a8a; --mut2:#5f5f5f;
}
*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--bg);color:var(--txt);
  /* System fonts. Every OS is named explicitly so no script falls through to a
     last-resort face: Latin first, then Thai, then Chinese, Japanese, Korean. */
  font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI Variable","Segoe UI",Roboto,
    "Noto Sans Thai","Leelawadee UI","Sarabun",
    "Noto Sans SC","PingFang SC","Microsoft YaHei",
    "Noto Sans JP","Hiragino Sans","Yu Gothic",
    "Noto Sans KR","Apple SD Gothic Neo","Malgun Gothic",
    "Helvetica Neue",Arial,sans-serif;
  -webkit-font-smoothing:antialiased;padding:16px 14px 60px}
.wrap{max-width:1180px;margin:0 auto}

.langbar{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end;margin-bottom:16px}
.langbar button{
  background:transparent;border:1px solid var(--line);color:var(--mut);
  border-radius:999px;padding:7px 14px;font-size:12px;font-weight:700;cursor:pointer;
  font-family:inherit;transition:.15s}
.langbar button:hover{border-color:#3a3a3a;color:#ccc}
.langbar button.on{border-color:var(--coral-dim);color:var(--coral);background:#1a0716}
.langbar button:focus-visible{outline:2px solid var(--coral);outline-offset:2px}

.whatson{border:1px solid #3a0a26;border-radius:16px;
  background:linear-gradient(180deg,#1a0f0c,#100610);
  padding:16px 18px;margin-bottom:16px;
  display:grid;grid-template-columns:auto 1fr 1fr 1fr;gap:20px;align-items:center}
.whatson .lbl{font-size:10px;font-weight:800;letter-spacing:.2em;text-transform:uppercase;color:var(--coral)}
.whatson .it{border-left:1px solid #330f24;padding-left:18px}
.whatson .it .d{font-size:9px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--mut2);margin-bottom:4px}
.whatson .it .t{font-size:13px;font-weight:700;line-height:1.35}

.tariffs{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:22px}
.tar{border:1px solid var(--line);border-radius:14px;padding:14px 16px;background:var(--card)}
.tar .k{font-size:11px;letter-spacing:.16em;text-transform:uppercase;font-weight:800;margin-bottom:6px}
.tar.h .k{color:var(--coral)}
.tar .v{font-size:13px;color:var(--mut);line-height:1.5}

.hero{border:1px solid #4a0b32;border-radius:18px;padding:26px 24px;margin-bottom:26px;
  background:linear-gradient(180deg,#170a12,#0d070b);position:relative}
.eyebrow{font-size:11px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;color:var(--coral);margin-bottom:10px}
.hero h1{font-size:34px;font-weight:800;letter-spacing:-.02em;line-height:1.05;margin-bottom:8px}
.spec{font-size:14px;color:var(--mut);margin-bottom:20px;line-height:1.5}
.pill{border:1px solid var(--coral-dim);color:var(--coral);border-radius:999px;
  padding:6px 14px;font-size:10px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;display:inline-block}
.hero .pill{position:absolute;top:24px;right:24px}
.card .pill{float:right;margin:0 0 8px 14px}
.card table,.card .rules,.card .list{clear:both}
@media(max-width:520px){.card .pill{float:none;margin:0 0 12px}}

.grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.card{border:1px solid var(--line);border-radius:18px;padding:24px 22px;background:var(--card)}
.card h2{font-size:26px;font-weight:800;letter-spacing:-.02em;margin-bottom:6px}
.card h2 span{color:var(--mut2);font-weight:700}
.tag{font-size:15px;font-weight:700;margin-bottom:4px}
.card .spec{font-size:13px;margin-bottom:18px}

table{width:100%;border-collapse:collapse}
th{font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--mut2);padding:0 0 9px;text-align:right}
th:first-child{text-align:left}
th.hh{color:var(--coral-dim)}
td{padding:9px 0;border-top:1px solid #1c1c1c;text-align:right;font-variant-numeric:tabular-nums}
td:first-child{text-align:left;font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--mut)}
td.hh{color:var(--coral);font-size:17px;font-weight:700}
td.pp{color:#fff;font-size:19px;font-weight:800}
td small{font-size:11px;color:var(--mut2);font-weight:600}
tr.sep td{border-top:1px solid #2f2f2f}
/* A heading row partway down a table, for where the unit changes: the Hall
   Console is priced per player above it and per whole sofa below. */
tr.subhead th{border-top:1px solid #2f2f2f;padding:15px 0 9px}
.note{font-size:12px;color:var(--mut2);margin-top:14px;line-height:1.55}

.section{font-size:11px;font-weight:800;letter-spacing:.2em;text-transform:uppercase;color:var(--mut2);margin:30px 0 14px}
.full{grid-column:1/-1}
.list{list-style:none;display:grid;grid-template-columns:1fr 1fr;gap:14px 26px}
.list li{border-top:1px solid #1c1c1c;padding-top:12px;display:flex;justify-content:space-between;gap:16px;align-items:baseline}
.list .n{font-size:14px;font-weight:700}
.list .d{font-size:12px;color:var(--mut2);margin-top:3px;line-height:1.5}
.list .p{font-size:19px;font-weight:800;white-space:nowrap}
.list .p small{font-size:11px;color:var(--mut2);font-weight:600}

.rules{display:grid;grid-template-columns:1fr 1fr;gap:22px 30px;margin-top:4px}
.rule{display:flex;gap:14px;align-items:flex-start}
.rule svg{flex:0 0 26px;width:26px;height:26px;stroke:var(--coral);stroke-width:1.5;
  fill:none;stroke-linecap:round;stroke-linejoin:round;opacity:.85;margin-top:1px}
.rule .rt{font-size:13.5px;line-height:1.55;color:#c9c9c9}


/* ===== цветовое зонирование, как в зале ===== */
.card,.hero{--z:var(--coral);--zd:var(--coral-dim)}
.z-racing{--z:#FF4438;--zd:#8f2a22}
.z-vr    {--z:#EA009A;--zd:#B00074}
.z-pc    {--z:#22D3EE;--zd:#1a8ea3}
.z-none  {--z:#9A9AA4;--zd:#4a4a52}
.zstrip{width:64px;height:3px;border-radius:99px;background:var(--z);opacity:.9;margin:-4px 0 18px}
.section .zdot{display:inline-block;width:26px;height:3px;border-radius:99px;
  background:#EA009A;vertical-align:middle;margin-right:10px;opacity:.9}
.card .pill{border-color:var(--zd);color:var(--z)}
.card td.hh{color:var(--z)}
.card th.hh{color:var(--zd)}
.hero .eyebrow{background:linear-gradient(90deg,#EA009A,#FF4438,#22D3EE);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.hero:not(.offer){border:1px solid transparent;
  background-image:linear-gradient(180deg,#170a12,#0d070b),
                   linear-gradient(120deg,#EA009A 0%,#FF4438 50%,#22D3EE 100%);
  background-origin:border-box;background-clip:padding-box,border-box}
@media(max-width:860px){
  .grid,.list,.tariffs,.rules{grid-template-columns:1fr}
  .whatson{grid-template-columns:1fr}
  .whatson .it{border-left:none;border-top:1px solid #330f24;padding-left:0;padding-top:12px}
  .hero h1{font-size:27px}
  .hero .pill{position:static;margin-bottom:12px}
  .card h2{font-size:23px}
  .langbar{justify-content:flex-start}
}


/* если JS не отработал — тема всё равно применится по настройке системы */
@media (prefers-color-scheme: light){
  html:not([data-theme="dark"]){
    --bg:#FBFBFD; --card:#FFFFFF; --line:#E6E6EE;
    --coral:#C4007F; --coral-dim:#E6A6CE;
    --txt:#111114; --mut:#5F5F6B; --mut2:#95959F;
    /* Without this a white logo would sit invisibly on a white page whenever
       JavaScript is off and the phone is set to light. */
    --logo-filter:none;
  }
  html:not([data-theme="dark"]) body{background:var(--bg);color:var(--txt)}
}
/* ================= СВЕТЛАЯ ТЕМА ================= */
/* по умолчанию берётся из настроек телефона; кнопка в шапке переключает вручную */
html[data-theme="light"]{
  --bg:#FBFBFD; --card:#FFFFFF; --line:#E6E6EE;
  --coral:#C4007F; --coral-dim:#E6A6CE;
  --txt:#111114; --mut:#5F5F6B; --mut2:#95959F;
}
html[data-theme="light"] body{background:var(--bg);color:var(--txt)}
html[data-theme="light"] .card,
html[data-theme="light"] .tar,
html[data-theme="light"] .qc,
html[data-theme="light"] .offer{background:#fff;border-color:var(--line)}
html[data-theme="light"] .hero,
html[data-theme="light"] .offer.hero{background:linear-gradient(180deg,var(--hbg,#fff),#fff)}
html[data-theme="light"] .whatson{background:linear-gradient(180deg,#FFF4FB,#FFFBFD);border-color:#F2C6E2}
html[data-theme="light"] td{border-top-color:#EFEFF4}
html[data-theme="light"] tr.sep td{border-top-color:#DEDEE8}
html[data-theme="light"] tr.subhead th{border-top-color:#DEDEE8}
html[data-theme="light"] .list li,
html[data-theme="light"] .qa{border-top-color:#EFEFF4}
html[data-theme="light"] td.pp,
html[data-theme="light"] .list .p,
html[data-theme="light"] .qc .qp,
html[data-theme="light"] .offer h3,
html[data-theme="light"] h1,
html[data-theme="light"] h2,
html[data-theme="light"] .tag,
html[data-theme="light"] .list .n,
html[data-theme="light"] .whatson .it .t{color:var(--txt)}
html[data-theme="light"] .rule .rt{color:#3C3C46}
html[data-theme="light"] .lede p,
html[data-theme="light"] .info .card p,
html[data-theme="light"] .offer p,
html[data-theme="light"] .rp{color:#4A4A56}
html[data-theme="light"] .fact{color:#2A2A33}
html[data-theme="light"] .bigcta{color:#fff}
html[data-theme="light"] .topnav .brand{color:var(--txt)}
html[data-theme="light"] .fullbtn:hover{color:var(--coral)}
html[data-theme="light"] footer{border-top-color:var(--line)}

/* зоны на светлой теме: неоновые оттенки на белом выцветают, берём затемнённые пары */
html[data-theme="light"] .z-racing{--z:#D02A1E;--zd:#EBB9B3}
html[data-theme="light"] .z-vr    {--z:#C4007F;--zd:#EFB4DA}
html[data-theme="light"] .z-pc    {--z:#0C7F96;--zd:#A9D6DF}
html[data-theme="light"] .z-none  {--z:#5F5F6B;--zd:#D3D3DA}
html[data-theme="light"] .hero:not(.offer){
  background-image:linear-gradient(180deg,#FFF4FB,#FFFBFD),
                   linear-gradient(120deg,#EA009A 0%,#FF4438 50%,#22D3EE 100%)}

.offer{--z:var(--coral);--zd:var(--coral-dim);border-color:var(--zd)}
.offer .pr{color:var(--z)}
/* цвет зоны должен побеждать общее правило .offer — отсюда двойной класс */
.offer.z-racing{--z:#FF4438;--zd:#8f2a22;--hbg:#1A0A08}
.offer.z-vr    {--z:#EA009A;--zd:#B00074;--hbg:#170A12}
.offer.z-pc    {--z:#22D3EE;--zd:#1a8ea3;--hbg:#08131A}
.offer.z-none  {--z:#9A9AA4;--zd:var(--line);--hbg:#121212}
html[data-theme="light"] .offer.z-racing{--z:#D02A1E;--zd:#EBB9B3;--hbg:#FFF6F5}
html[data-theme="light"] .offer.z-vr    {--z:#C4007F;--zd:#EFB4DA;--hbg:#FFF4FB}
html[data-theme="light"] .offer.z-pc    {--z:#0C7F96;--zd:#A9D6DF;--hbg:#F2FAFC}
html[data-theme="light"] .offer.z-none  {--z:#5F5F6B;--zd:var(--line);--hbg:#fff}
.offer.z-lvl3{border:1px solid transparent;box-shadow:none;
  background-image:linear-gradient(var(--card),var(--card)),
                   linear-gradient(120deg,#EA009A 0%,#FF4438 50%,#22D3EE 100%);
  background-origin:border-box;background-clip:padding-box,border-box}
.offer.z-lvl3 .pr{background:linear-gradient(90deg,#EA009A,#FF4438,#22D3EE);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.offer.z-none{border-color:var(--line)}
/* переключатель */
body{background:var(--bg);color:var(--txt);min-height:100vh}
.themebtn{background:transparent;border:1px solid var(--line);color:var(--mut);border-radius:999px;
  padding:6px 12px;font-size:12px;font-weight:700;cursor:pointer;font-family:inherit;line-height:1.4}
.themebtn:hover{border-color:var(--coral-dim);color:var(--coral)}

.lede{border:1px solid var(--line);border-radius:18px;background:var(--card);padding:26px 24px;margin-bottom:16px}
.lede h1{font-size:30px;font-weight:800;letter-spacing:-.02em;line-height:1.1;margin-bottom:10px}
.lede .sub{font-size:15px;color:var(--coral);font-weight:700;margin-bottom:12px}
.lede p{font-size:14px;color:var(--mut);line-height:1.6;max-width:70ch}
.info{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:26px}
.info .card h3{font-size:11px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;color:var(--coral);margin-bottom:10px}
.info .card p{font-size:13.5px;color:#c2c2c2;line-height:1.6}
.info .card a{color:#fff}
/* This rule was written for an <a>. "Book a session" is now a <button>, which
   arrives with a browser border, its own font and a text cursor — none of which
   an anchor has, and all of which showed. */
.bigcta{display:inline-block;background:var(--coral);color:#FFFFFF;font-weight:800;font-size:15px;
  text-decoration:none;border-radius:999px;padding:14px 28px;margin-top:24px;
  border:0;cursor:pointer;font-family:inherit;line-height:1.2;
  -webkit-appearance:none;appearance:none}
.rp{font-size:14.5px;color:#c9c9c9;line-height:1.65;margin-bottom:12px;max-width:75ch}
footer{margin-top:40px;padding-top:20px;border-top:1px solid var(--line);
  font-size:12px;color:var(--mut2);line-height:1.7}
footer a{color:var(--mut)}
.offers{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:22px}
.offer{border:1px solid var(--line);border-radius:16px;background:var(--card);padding:20px 22px}
.offer.hero{border-color:#4a0b32;background:linear-gradient(180deg,#170a12,#0d070b)}
.offer h3{font-size:20px;font-weight:800;letter-spacing:-.01em;margin-bottom:4px}
.offer .pr{font-size:13px;font-weight:800;color:var(--coral);margin-bottom:9px}
.offer .pr b{font-weight:800}
.offer p{font-size:13.5px;color:#b4b4b4;line-height:1.6}
.fullbtn{display:block;text-align:center;border:1px solid var(--line);border-radius:14px;
  padding:16px;color:var(--mut);text-decoration:none;font-weight:700;font-size:14px;margin-bottom:26px}
.fullbtn:hover{border-color:var(--coral-dim);color:var(--coral)}

.topnav{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:10px 18px;margin-bottom:20px}
.topnav .brand{justify-self:start}
.topnav .brand{display:flex;align-items:center;gap:10px;text-decoration:none;font-size:18px;font-weight:800;letter-spacing:-.02em}
/* width:auto meant the box was sized by whatever was inside it. With no
   logo.png yet, that was the alt text — so every page load laid out the words
   "Level3 Hub" at text width, then onerror swapped in the placeholder and the
   width snapped to 60px, shoving the menu sideways. Switching language is a
   full page load, so it happened on every switch. A fixed box removes the
   whole sequence; object-fit keeps a real logo's proportions once one exists. */
/* The lockup is 2.30:1, so 78px at 34px tall. Fixed either way, so a missing
   file cannot resize the box. */
.topnav .brand img{height:34px;width:78px;object-fit:contain;display:block;
  filter:var(--logo-filter)}
/* The artwork is red. On the dark theme brightness(0) crushes every pixel to
   black and invert(1) flips it, giving pure white from the same file — no
   second asset to keep in step. On the light theme the mark keeps its own red,
   which is what it is drawn for, and white would vanish against the page.
   This is how Level3.Web's own price page does it. */
:root{--logo-filter:brightness(0) invert(1)}
html[data-theme="light"]{--logo-filter:none}
/* Alt text must never lay out either — it is what was being measured. Screen
   readers still announce it; it just no longer draws or takes up space. */
.topnav .brand img,.hero-img,.fact img{color:transparent;font-size:0}
/* 18px put Home, Prices and Sim Racing close enough to read as one run of
   words rather than three separate places to go. */
/* margin-right:auto pinned the menu to the logo's shoulder and pushed all the
   slack to one side, so the header was two crowded clumps with a hole between
   them. margin:0 auto puts the slack on both sides instead and the menu lands
   in the space that was empty. */
.secnav{display:flex;gap:46px;flex-wrap:wrap;align-items:baseline;justify-self:center;margin:0}
.navlink{font-size:15px;font-weight:800;color:var(--mut);text-decoration:none;
  padding-bottom:3px;border-bottom:2px solid transparent}
.navlink:hover{color:var(--txt)}
.navlink.on{color:var(--txt);border-bottom-color:var(--coral)}
.langnav{display:flex;gap:14px;flex-wrap:wrap;align-items:center;justify-self:end}
/* Six outlined buttons carried more weight than the navigation did — the eye
   went to the language row first, which is backwards. As plain text they read
   as the secondary control they are, and the menu becomes the loudest thing in
   the bar. Only the current language is marked, in the accent. */
.langnav .l{border:0;color:var(--mut2);border-radius:0;
  padding:4px 2px;font-size:12px;font-weight:700;text-decoration:none;
  border-bottom:2px solid transparent}
.langnav .l:hover{color:var(--txt)}
.langnav .l.on{color:var(--coral);border-bottom-color:var(--coral-dim)}
/* The theme toggle sat immediately left of "English", so it read as a seventh
   language. It now sits after the six, at the far end of the header where a
   display control belongs, behind a divider and a wider gap so the eye groups
   the languages together and the toggle on its own. */
.langnav .themebtn{margin-left:14px;padding-left:16px;border:0;border-radius:0;
  border-left:1px solid var(--line);font-size:15px;line-height:1}
.langnav .themebtn:hover{border-left-color:var(--line);color:var(--coral)}
/* The phone's language control. Hidden on desktop, where there is room to show
   all six as pills and one tap beats two. The chevron is drawn inline so the
   control needs no image file. */
.langsel{display:none;-webkit-appearance:none;appearance:none;
  background-color:transparent;border:1px solid var(--line);color:var(--mut);
  border-radius:999px;padding:7px 28px 7px 13px;font-family:inherit;
  font-size:12px;font-weight:700;line-height:1.2;cursor:pointer;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%238a8a8a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat:no-repeat;background-position:right 11px center;background-size:9px 6px}
/* iOS and Android draw the open list themselves and ignore the page's theme,
   so the options are given readable colours of their own. */
.langsel option{color:#111114;background:#fff}
.contacts .cline{font-size:13.5px;color:var(--mut);margin-bottom:14px;line-height:1.6}
.cbtns{display:flex;flex-wrap:wrap;gap:9px}
.cbtn{border:1px solid var(--line);border-radius:999px;padding:10px 18px;font-size:13px;
  font-weight:700;text-decoration:none;color:var(--txt)}
.cbtn:hover{border-color:var(--coral-dim);color:var(--coral)}
/* 1200, not 700, because of what the desktop header actually costs. Its grid
   is 1fr auto 1fr, and equal outer columns mean the logo's column is forced as
   wide as the language row beside it — around 420px each. With the menu
   between them the whole bar needs roughly 1150px, which only the full-width
   layout has. An iPad is nowhere near it in either orientation, so it was
   getting the desktop header and the six pills were spilling.

   Anything narrower than a laptop gets the compact header instead. */
/* Below a laptop, the six pills come out and the dropdown goes in — and that
   is ALL that changes. The header keeps its three-column grid, so the menu
   stays in the middle of the top row.

     logo ......... Home  Prices  Sim Racing ......... [language v] [theme]

   Previously this breakpoint also dropped the menu onto a second row, which
   was a phone rule that had no business firing on a tablet: it left the whole
   middle of the header empty and put the menu under the logo for no reason.
   With one small dropdown instead of six pills the bar needs about 570px, so
   there is room to spare on anything wider than a phone. */
@media(max-width:1200px){
  .langnav .l{display:none}
  .langsel{display:block}
  .langnav{gap:8px}
  /* No divider once the pills are gone — there is nothing left to divide it
     from, and the rule would just be a stray mark. */
  .langnav .themebtn{margin-left:0;padding:6px 11px;border:1px solid var(--line);
    border-radius:999px;font-size:14px}
  .secnav{gap:34px}
}

/* Only on a phone does the menu need a row of its own — three words plus a
   logo plus the language control genuinely will not fit across 390px.

     row 1   logo .................... [language v] [theme]
     row 2   Home   Prices   Sim Racing

   Back to flex for that, because the grid would squeeze the menu into a
   middle column instead of letting it span. */
@media(max-width:700px){
  .topnav{display:flex;flex-wrap:wrap;gap:14px 12px;margin-bottom:22px}
  .topnav .brand{order:0;justify-self:auto}
  .langnav{order:1;width:auto;margin-left:auto;justify-self:auto}
  .secnav{order:2;gap:26px;width:100%;margin:0;justify-self:auto}
}
/* No fixed ratio. The banner keeps whatever shape the photograph was cropped
   to, so a picture framed by hand is never re-cropped by the stylesheet and
   a differently shaped one can be dropped in without touching any CSS. The
   width and height attributes on the <img> reserve the right space before it
   loads, so nothing jumps. */
/* ===== Banner colour treatment =====
   The room is lit magenta and blue, but a phone camera in a dark room flattens
   that into a fairly even purple. This lifts it back without touching the file,
   so the grade stays adjustable and the original photograph is never degraded.

   Most of the work is the saturation, not the colour wash. An overlay blend was
   tried first and was invisible: overlay barely moves a backdrop this dark, so
   the whole effect landed on nothing. Screen does move dark pixels, but pushed
   hard it lifts the blacks and the seat turns a hazy grey-purple. Held light,
   with the saturation carrying the load, the wall stripes and the wheel LEDs
   come back while the blacks stay black and the rally footage on the screens
   keeps its own colour.

   Three layers, weakest first:
     filter     saturation and contrast, which is what actually does it
     ::before   the brand gradient, screened into the dark areas only
     ::after    a dark fade at the bottom edge, so the banner sits down into the
                page instead of stopping dead against it

   --tint is the one number to change if the colour wants to be stronger or
   weaker. 0 removes the wash and leaves the saturation lift by itself. */
.heroshot{--tint:.17;
  position:relative;border-radius:18px;overflow:hidden;margin-bottom:16px;
  line-height:0;isolation:isolate}
.hero-img{width:100%;height:auto;display:block;
  filter:saturate(1.6) contrast(1.14)}
.heroshot::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(115deg,
    rgba(234,0,154,var(--tint)) 0%,
    rgba(255,68,56,calc(var(--tint) * .55)) 48%,
    rgba(34,211,238,calc(var(--tint) * .8)) 100%);
  mix-blend-mode:screen}
.heroshot::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,0) 58%,rgba(6,6,8,.45) 100%)}
/* On the light theme the page behind is white, so a dark foot on the banner
   reads as dirt rather than depth. */
html[data-theme="light"] .heroshot::after{
  background:linear-gradient(180deg,rgba(0,0,0,0) 70%,rgba(6,6,8,.22) 100%)}
.facts{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:22px}
.fact{border:1px solid var(--line);border-radius:14px;background:var(--card);padding:12px 14px;
  font-size:12.5px;font-weight:700;color:#d8d8d8;display:flex;gap:11px;align-items:center;line-height:1.4}
.fact img{width:48px;height:48px;object-fit:cover;border-radius:9px;flex:0 0 48px}
@media(max-width:860px){.info,.offers{grid-template-columns:1fr}.lede h1{font-size:24px}
  /* The banner keeps its shape on a phone too. Squaring it up to 16:9 here
     would make the browser crop the sides, and the sides are where the second
     rig is — the whole reason this frame was chosen. */
  .facts{grid-template-columns:1fr}}

/* ===== Zone colour on the service cards =====
   Must come last: the plain .offer rules further up the file would otherwise
   win on equal specificity and turn every card magenta.

   Each of the six cards used to carry its zone colour as a full border, and two
   of them a tinted background on top of that, so the front page was six
   coloured frames stacked in a grid and the colour stopped meaning anything.
   The zone now shows as a short bar down the left edge and in the price, and
   the frame itself is the same neutral line as every other card on the site.
   Same information, one loud element per card instead of three. */
.offer{position:relative;border-color:var(--line);padding-left:26px;overflow:hidden}
.offer::before{content:"";position:absolute;left:0;top:14px;bottom:14px;width:3px;
  border-radius:0 99px 99px 0;background:var(--z);opacity:.9}
.offer .pr{color:var(--z)}
.offer.hero{border-color:var(--line);background:var(--card)}
.offer.z-none::before{opacity:.55}
.offer.z-lvl3{border:1px solid var(--line);background:var(--card)}
.offer.z-lvl3::before{background:linear-gradient(180deg,#EA009A,#FF4438,#22D3EE)}
.offer.z-lvl3 .pr{background:linear-gradient(90deg,#EA009A,#FF4438,#22D3EE);
  -webkit-background-clip:text;background-clip:text;color:transparent}
html[data-theme="light"] .offer,
html[data-theme="light"] .offer.hero,
html[data-theme="light"] .offer.z-lvl3{background:#fff;border-color:var(--line)}
/* The dimmed pair is for a 1px line on a dark ground; on a 3px bar in daylight
   it reads as washed out, so the bar takes the full zone colour instead. */
html[data-theme="light"] .offer::before{opacity:1}

html[data-theme="light"] .hero:not(.offer){border:1px solid transparent;
  background-image:linear-gradient(180deg,#FFF4FB,#FFFBFD),
                   linear-gradient(120deg,#EA009A 0%,#FF4438 50%,#22D3EE 100%);
  background-origin:border-box;background-clip:padding-box,border-box}
/* Address, opening hours and phone in the "how to find us" card. Google
   matches a Business Profile against the name, address and phone on the
   site, so these have to be real text on the page, not only in the JSON-LD. */
.card .addr,.card .hours{font-size:13.5px;line-height:1.6;margin-top:10px;color:#c2c2c2}
.card .addr b{color:var(--txt);font-weight:700}
.card .hours b{color:var(--coral);font-weight:700}
.card .tel{margin-top:6px;font-size:13.5px}
.card .tel a{color:var(--txt);font-weight:700;text-decoration:none}
.card .tel a:hover{color:var(--coral)}
html[data-theme="light"] .card .addr,
html[data-theme="light"] .card .hours{color:#4A4A56}

/* Every interactive control needs a visible keyboard focus ring; only the
   language buttons had one. */
a:focus-visible,button:focus-visible{outline:2px solid var(--coral);outline-offset:2px;border-radius:6px}

@media (prefers-reduced-motion: reduce){
  *{transition:none !important;animation:none !important}
}


/* ===== Placeholders where the photographs will go =====
   The images do not exist yet. Rather than vanishing — which hid whole rows of
   the layout — a failed image keeps its exact box and paints a soft block in
   the colour of the zone it belongs to, dashed so it never reads as finished
   artwork. onerror swaps in a 1x1 transparent GIF first, so no browser draws a
   broken-image icon or the alt text over the top. */
img.ph{border:1px dashed var(--line-ph,#3a3a3a);background-color:var(--card)}
.hero-img.ph{background-image:linear-gradient(120deg,
  rgba(234,0,154,.22) 0%,rgba(255,68,56,.22) 50%,rgba(34,211,238,.22) 100%)}
.fact img.ph{background-image:linear-gradient(135deg,rgba(255,68,56,.30),rgba(255,68,56,.10))}
.fact:nth-child(2) img.ph{background-image:linear-gradient(135deg,rgba(34,211,238,.30),rgba(34,211,238,.10))}
.fact:nth-child(3) img.ph{background-image:linear-gradient(135deg,rgba(234,0,154,.30),rgba(234,0,154,.10))}
.topnav .brand img.ph{background-image:linear-gradient(100deg,
  rgba(234,0,154,.35),rgba(255,68,56,.35),rgba(34,211,238,.35))}
html[data-theme="light"] img.ph{--line-ph:#D0D0DA}

/* ===== Booking sheet =====
   The button used to scroll to the contact row at the foot of the page, which
   on a phone is several screens away and reads as if nothing happened. */
/* A modal <dialog> is centred by the browser with margin:auto — which the
   `*{margin:0}` reset at the top of this file silently removed, dropping the
   sheet into the top-left corner on desktop. Positioned explicitly so no reset
   can take it away again. */
dialog.booksheet{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);
  margin:0;max-height:calc(100vh - 40px);overflow:auto;
  border:1px solid var(--line);border-radius:20px;background:var(--card);
  color:var(--txt);padding:24px 22px;max-width:400px;width:calc(100% - 32px);
  font-family:inherit}
dialog.booksheet::backdrop{background:rgba(0,0,0,.65)}
html[data-theme="light"] dialog.booksheet::backdrop{background:rgba(20,20,26,.45)}
dialog.booksheet h3{font-size:19px;font-weight:800;letter-spacing:-.01em;margin-bottom:6px}
dialog.booksheet .bs-sub{font-size:13px;color:var(--mut);line-height:1.55;margin-bottom:18px}
/* Opening a modal moves focus to its first focusable child, which put the
   coral focus ring around LINE and made it look pre-selected. Focus goes to
   the panel itself instead — the ring is pointless on a container, and Tab
   still reaches the four channels in order for anyone using a keyboard. */
dialog.booksheet:focus{outline:none}
dialog.booksheet .bs-ch{display:grid;gap:9px}
dialog.booksheet .bs-ch a{display:block;text-align:center;border:1px solid var(--line);
  border-radius:999px;padding:13px 18px;font-size:14px;font-weight:700;
  text-decoration:none;color:var(--txt)}
dialog.booksheet .bs-ch a:hover{border-color:var(--coral-dim);color:var(--coral)}
dialog.booksheet .bs-close{margin-top:16px;width:100%;background:transparent;
  border:0;color:var(--mut2);font-size:13px;font-weight:700;cursor:pointer;
  font-family:inherit;padding:8px}
dialog.booksheet .bs-close:hover{color:var(--coral)}

/* ===== Which tariff is running right now =====
   The same signal the counter iPad gives, computed in the browser from Bangkok
   time so the public site needs no connection to the cafe.

   The iPad also dims the column that does not apply, because it is read at the
   counter by someone paying in the next minute. This page is read by someone
   deciding whether to come at all, quite possibly at midnight for a visit on
   Tuesday afternoon, so both columns stay fully legible and only the badge
   moves. */
.tar{position:relative}
.nowpill{display:none;position:absolute;top:12px;right:14px;
  background:var(--coral);color:#fff;border-radius:999px;
  padding:3px 9px;font-size:9px;font-weight:800;letter-spacing:.12em}
.tar.now .nowpill{display:inline-block}
.tar.now{border-color:var(--coral-dim)}

/* ===== Touch =====
   Keyed on the pointer, not the screen width: a 1024px tablet is a touch
   device and a 1024px window on a laptop is not, and it is the finger that
   decides how big a control has to be. WCAG asks for 44px, and the language
   control and the theme toggle were both around 28px — fine for a mouse,
   a fiddle for a thumb, and the language names sit close enough together
   that a near miss lands on the wrong one. */
@media (pointer: coarse){
  .langsel{min-height:44px;padding-top:0;padding-bottom:0}
  .langnav .themebtn{min-height:44px;min-width:44px;padding:0 12px}
  .navlink{padding-top:8px;padding-bottom:10px}
  .langnav .l{padding:10px 4px}
  .cbtn{padding:13px 20px}
}

/* The badge before opening. Muted, because "from 09:00" is information about
   later rather than a price running now, and it should not read with the same
   weight as the live one. */
.tar.now.soon .nowpill{background:transparent;color:var(--mut);
  border:1px solid var(--line);padding:2px 8px}
.tar.now.soon{border-color:var(--line)}

/* ===== "share it" =====
   Marks the prices that cover the whole thing however many of you turn up.
   The information was already in the header — "per rig" against "per seat" —
   but that is one quiet word carrying a large difference: four on the sofa pay
   once, four on PC seats pay four times. Worth being able to see rather than
   having to read for. Takes the zone's colour, so it belongs to its card. */
/* Neutral on purpose. Taking the zone colour put a magenta chip on four of
   the six cards that carry one, which drowned the page and left the "2 for 1"
   offer competing with labels rather than standing out from them. A label and
   an offer should not look alike: this one catches the eye by contrast, not by
   hue, and the only coloured chip on the page is now the one worth chasing. */
.shr{display:inline-block;margin-left:8px;padding:2px 8px;border-radius:999px;
  border:0;background:rgba(255,255,255,.09);color:#d5d5db;
  font-size:8.5px;font-weight:800;letter-spacing:.08em;vertical-align:middle;
  white-space:nowrap}
html[data-theme="light"] .shr{background:rgba(20,20,26,.07);color:#4A4A56}
tr.subhead th .shr{margin-left:10px}

/* ===== the second-seat offer =====
   Filled rather than outlined, unlike the "share it" chip: that one labels
   what a price means, this one is the best offer on the page and should read
   as one. It sits inside the Happy Hours column header because that is the
   only place it can be this short and still be true — "2 for 1" under the
   words "Happy Hours" carries its own condition. On the card as a pill it
   would have needed the condition spelled out, or become the sort of
   unconditional claim the rest of this page has been losing. */
.deal{display:inline-block;margin-left:8px;padding:2px 8px;border-radius:999px;
  background:var(--coral);color:#fff;font-size:8.5px;font-weight:800;
  letter-spacing:.08em;vertical-align:middle;white-space:nowrap}
html[data-theme="light"] .deal{color:#fff}
