/* ============================================================
   core.css — halilerencelik.com
   Tokens, base type, and the components every page shares.
   Loaded first on every page; page files add only what is theirs.
   ============================================================ */

@font-face{
  font-family:"Inter Variable";
  src:url("../fonts/Inter-Variable.woff2") format("woff2-variations"),
      url("../fonts/Inter-Variable.ttf") format("truetype");
  font-style:normal;font-weight:100 900;font-display:swap;
}

:root{
  /* --- surface ------------------------------------------------ */
  --canvas:#030304;          /* page ground                       */
  --raised:#0B0C0E;          /* card, panel                       */
  --sunk:#08090A;            /* inset cell inside a card          */

  /* --- ink ---------------------------------------------------- */
  --ink:#F7F7FA;             /* 19.3:1 on canvas                  */
  --ink-2:#ABADB5;           /*  9.2:1 — body                     */
  --ink-3:#858A96;           /*  6.0:1 — meta, labels             */

  /* --- line --------------------------------------------------- */
  --rule:#1E2126;            /* decorative divider                */
  --rule-2:#2E333A;          /* decorative divider, emphasised    */
  --edge:#5A606A;            /*  3.1:1 — real component boundary  */

  /* --- accent ------------------------------------------------- */
  --ember:#FF6A00;           /*  7.2:1 on canvas                  */

  /* --- family ------------------------------------------------- */
  --sans:"Inter Variable","Inter","Helvetica Neue",Arial,sans-serif;
  /* One family carries the whole site. The monospace face below is not
     a second voice: it appears only inside code, where the alignment of
     characters is the meaning. Nothing else may reach for it, and
     nothing on the site is set in capitals — a label is separated from
     body text by size, colour and space, never by shouting. */
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;

  /* --- display scale: screens, headings, interface ------------- */
  --t-display:clamp(1.875rem,5.6vw,3.75rem);   /* page h1                */
  --t-title:clamp(1.5rem,3.4vw,2.375rem);     /* card title, closing h2 */
  --t-head:clamp(1.1875rem,2.2vw,1.5rem);      /* section h2             */
  --t-lead:clamp(0.9375rem,1.6vw,1.1875rem);   /* standfirst             */
  --t-num:1.25rem;                          /* a figure or a count   */
  --t-sub:1.125rem;                          /* item heading, list nm */
  --t-body-l:clamp(1.0625rem,1.7vw,1.1875rem);     /* emphasised body       */
  --t-body:1.0625rem;
  --t-body-s:1rem;
  --t-meta:0.9375rem;
  --t-label:0.875rem;                        /* register label        */
  --t-mono:0.875rem;                         /* code only, never smaller */
  --t-figure:clamp(1.625rem,3vw,2rem);       /* a figure, alone       */
  --t-close:clamp(1.625rem,4.4vw,3.125rem);      /* the closing statement */

  /* --- reading scale: long prose only (blog body) -------------- */
  --t-read:clamp(1.0625rem,1.35vw,1.1875rem);
  --t-read-h2:clamp(1.3125rem,2.2vw,1.625rem);
  --t-read-h3:clamp(1.125rem,1.6vw,1.25rem);
  --t-read-lead:clamp(1.125rem,1.6vw,1.3125rem);  /* prose lead, blockquote */
  --t-read-title:clamp(1.75rem,4.4vw,2.875rem); /* a note's own h1        */
  --lh-read:1.72;
  --measure-read:54ch;   /* ~68 characters, measured, not assumed */

  /* --- space: named by value, so a rule reads as its own spec --- */
  --s4:4px;   --s8:8px;   --s12:12px; --s16:16px; --s20:20px;
  --s24:24px; --s32:32px; --s40:40px; --s48:48px; --s64:64px;
  /* fluid space: six steps, each named by the range it covers */
  --f16-24:clamp(16px,2.4vw,24px);  --f22-32:clamp(22px,3vw,32px);
  --f26-40:clamp(26px,3.6vw,40px);  --f30-52:clamp(30px,4.4vw,52px);
  --f34-72:clamp(34px,6vw,72px);    --f38-86:clamp(38px,7vw,86px);
  --pad-sec:clamp(40px,5.6vw,74px);
  --gut:16px;

  /* --- measure ------------------------------------------------ */
  --maxw:1240px;
  --maxw-read:37.5rem;

  /* --- shape and motion --------------------------------------- */
  --r:0;
  --ease:cubic-bezier(.16,.84,.34,1);
  --dur-1:.18s; --dur-2:.22s; --dur-3:.45s;
}
/* ---------- the light page ------------------------------------ */
/* One page family sits on white: the architecture presentations, where
   plans and renders want a gallery wall, not a cinema. The shell, type
   and components are the same; only the ten surface, ink and line tokens
   turn over, plus the accent, which is too pale on white at #FF6A00. */
html[data-theme="light"]{
  --canvas:#FFFFFF; --raised:#F6F6F8; --sunk:#F1F1F4;
  --ink:#0B0C0E; --ink-2:#4A4F58; --ink-3:#666B75;
  --rule:#E5E6EA; --rule-2:#D3D5DB; --edge:#8B919C;
  --ember:#C24E00;
}
html[data-theme="light"] ::selection{color:#FFF}
html[data-theme="light"] .dbtn[aria-pressed="true"],
html[data-theme="light"] .tab[aria-selected="true"]{background:rgba(11,12,14,.05)}
@media(min-width:700px){:root{--gut:40px}}
@media(min-width:1024px){:root{--gut:56px}}

/* ---------- base ---------------------------------------------- */
*{box-sizing:border-box}
/* A control is text too. Left alone, the browser sets buttons and
   fields in its own face, which is how a second font gets onto a site
   nobody chose one for. */
button,input,select,textarea{font-family:inherit}
/* A component with its own display value ignores [hidden] otherwise —
   the demo launcher is display:flex and stayed on screen when hidden. */
[hidden]{display:none!important}
html{scroll-behavior:smooth}
body{
  /* One long unbroken token — a client name, a URL — must not push the page
     sideways. `anywhere`, not `break-word`: only `anywhere` also lowers the
     min-content size, which is what a grid column actually measures. */
  overflow-wrap:anywhere;
  margin:0;background:var(--canvas);color:var(--ink);
  font-family:var(--sans);font-size:var(--t-body);line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
@media(max-width:430px){body{font-size:var(--t-body-s)}}
img{display:block;max-width:100%}
::selection{background:var(--ember);color:#000}
a{color:inherit;text-decoration:none}
a:focus-visible,button:focus-visible{outline:2px solid var(--ember);outline-offset:3px}
/* Pressed. Touch has no hover, so this is the only answer a tap gets.
   No transition on purpose: feedback has to be immediate. */
a:active,button:active{opacity:.62}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 var(--gut)}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* ---------- register label ------------------------------------ */
.lab{
  font-size:var(--t-label);font-weight:400;
  letter-spacing:.01em;color:var(--ink-3);
}
a.lab{transition:color var(--dur-1) var(--ease)}
a.lab:hover,a.lab:focus-visible{color:var(--ember)}

/* ---------- header -------------------------------------------- */
.site-head{
  position:sticky;top:0;z-index:50;background:var(--canvas);
}
.head-in{
  max-width:var(--maxw);margin:0 auto;padding:0 var(--gut);
  /* The wordmark is gone from the head: the page says the name itself,
     and Home is in the menu. One child left, and it belongs on the right. */
  display:flex;align-items:center;justify-content:flex-end;gap:var(--s16);min-height:56px;
}
.brand{
  font-weight:400;font-size:var(--t-body-s);letter-spacing:-.01em;
  display:inline-flex;align-items:center;min-height:44px;
  transition:color var(--dur-1) var(--ease);
}
.brand:hover{color:var(--ember)}
.nav{display:none;gap:var(--s24);align-items:center}
@media(min-width:860px){.nav{display:flex}}
.nav a{
  font-size:var(--t-meta);color:var(--ink-2);display:inline-flex;align-items:center;min-height:44px;
  transition:color var(--dur-1) var(--ease);
}
.nav a:hover{color:var(--ink)}
.nav a[aria-current="page"]{color:var(--ink)}   /* here = brightest, never dimmest */
.menu-btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;min-width:44px;background:none;border:0;color:var(--ink);cursor:pointer;
  font-size:var(--t-label);letter-spacing:.01em;
}
@media(min-width:860px){.menu-btn{display:none}}
.panel{display:none;background:var(--raised)}
.panel.open{display:block}
.panel .wrap{padding-top:var(--s8);padding-bottom:var(--s20)}
.panel a{
  display:flex;align-items:center;min-height:52px;
  font-size:var(--t-sub);
}
.panel .lab{display:block;margin:var(--s16) 0 var(--s4)}

/* ---------- section frame --------------------------------------
   No rules between sections or under their heads any more: the reader
   asked for the lines to go, everywhere, and for space to do the
   separating instead. */
.sec .wrap{padding-top:var(--pad-sec);padding-bottom:var(--pad-sec)}
.sec-head{
  display:flex;justify-content:space-between;align-items:baseline;gap:var(--s16);flex-wrap:wrap;
  margin-bottom:var(--f22-32);
}

/* ---------- page head: About, /work/, 404 --------------------- */
.page-head .wrap{padding-top:var(--f34-72);padding-bottom:var(--f30-52)}
.page-head .lab{display:block;margin-bottom:var(--f16-24)}
.page-head h1{
  font-weight:700;font-size:var(--t-display);line-height:1.04;letter-spacing:-.035em;
  margin:0 0 var(--f16-24);max-width:16ch;text-wrap:balance;
}
.page-head .standfirst{
  font-size:var(--t-lead);line-height:1.48;color:var(--ink-2);max-width:52ch;margin:0;
}

/* ---------- field sections ------------------------------------ */
.field .wrap{padding-top:var(--pad-sec);padding-bottom:var(--pad-sec)}
.field-head{
  display:flex;justify-content:space-between;align-items:baseline;gap:var(--s16);flex-wrap:wrap;
  margin-bottom:var(--f22-32);
}
.field h2{font-weight:600;font-size:var(--t-head);letter-spacing:-.02em;margin:0}
.field p{color:var(--ink-2);font-size:var(--t-body);max-width:54ch;margin:0 0 var(--s16)}
.field p:last-child{margin-bottom:0}

/* From 1000px every field of the argument is heading-rail plus body. Before
   this the body stopped at 60% of the page and the right-hand 40% was empty
   on every section. The evidence section is deliberately outside this: the
   screenshots are the point there, and a rail would halve them. */
@media(min-width:1000px){
  .field:not(.evidence) .wrap{
    display:grid;grid-template-columns:minmax(0,240px) minmax(0,1fr);
    gap:0 var(--s48);align-items:start;
  }
  .field:not(.evidence) .field-head{
    grid-column:1;grid-row:1;display:block;
    border-bottom:0;padding-bottom:0;margin-bottom:0;
  }
  .field:not(.evidence) .field-head .lab{display:block;margin-top:var(--s8)}
  .field:not(.evidence) .wrap > :not(.field-head){grid-column:2}
}

/* ---------- work list: home page and /work/ ------------------- */
.flagship{
  display:block;border:1px solid var(--edge);background:var(--raised);
  padding:var(--f22-32);margin-bottom:var(--s16);position:relative;overflow:hidden;
  transition:border-color var(--dur-2) var(--ease);
}
.flagship:has(a:hover),.flagship:has(a:focus-visible){border-color:var(--ember)}
.flagship:has(a:active){box-shadow:inset 0 0 0 2px var(--ember)}
/* not opacity and not transform: .rev owns both of those on this element */
.flagship h3 a{display:inline-block;min-height:44px}
.flagship h3 a::after{content:"";position:absolute;inset:0;z-index:1}
.flagship h3 a:focus-visible{outline:none}
.flagship h3 a:focus-visible::after{outline:2px solid var(--ember);outline-offset:-3px}
.flagship:last-of-type{margin-bottom:var(--s24)}
.flagship .top{display:flex;justify-content:space-between;gap:var(--s12);flex-wrap:wrap;margin-bottom:var(--s16)}
.flagship h3{
  margin:0 0 var(--s8);font-weight:700;font-size:var(--t-title);
  letter-spacing:-.03em;line-height:1.05;
  transition:color var(--dur-2) var(--ease);
}
.flagship:has(a:hover) h3,.flagship:has(a:focus-visible) h3{color:var(--ember)}
.flagship .lead{margin:0 0 var(--s16);color:var(--ink-2);font-size:var(--t-body);max-width:60ch}
.flagship .led{
  margin:0 0 var(--s20);font-size:var(--t-body);color:var(--ink);max-width:54ch;
  padding-left:var(--s16);border-left:2px solid var(--ember);
}
.params{
  display:grid;grid-template-columns:1fr 1fr;gap:var(--s16) var(--s24);margin:0;
  padding-top:var(--s16);
}
/* a figure and its unit never separate at a line break */
.params .nb{white-space:nowrap}
.params div{min-width:0}
.params dt{font-size:var(--t-label);color:var(--ink-3);margin-bottom:var(--s4);letter-spacing:.01em;}
.params dd{margin:0;font-size:var(--t-meta);color:var(--ink-2);line-height:1.4}
.verdict{
  display:block;width:max-content;max-width:100%;font-size:var(--t-label);letter-spacing:.01em;
  color:var(--ink-3);border:1px solid var(--edge);padding:var(--s4) var(--s12);margin-bottom:var(--s16);
}
/* On one column the verdict follows the parameter grid directly, and with
   nothing between them the box landed on the last line of it — a border
   touching type reads as a collision, not as a label. Air on both sides
   here. Above 1000px the parameters are in the other column and the box
   keeps the spacing it already had. */
@media(max-width:999px){
  .verdict{margin-top:var(--s24);margin-bottom:var(--s20)}
}
.go{
  display:inline-flex;align-items:center;gap:var(--s8);min-height:44px;
  font-size:var(--t-body-s);font-weight:500;color:var(--ember);
}
.go span{transition:transform var(--dur-2) var(--ease)}
@media(hover:hover){.flagship:has(a:hover) .go span{transform:translate(3px,-3px)}}

/* From 1000px the card is a composition, not a wide box with a narrow
   paragraph in it: the argument runs down the left, the facts sit in a
   rail on the right. Below that width it stacks in source order. */
@media(min-width:1000px){
  .flagship{
    display:grid;grid-template-columns:minmax(0,1fr) minmax(0,340px);
    gap:0 var(--s48);align-items:start;
  }
  .flagship .top{grid-column:1/-1;grid-row:1}
  .flagship h3,.flagship .lead,.flagship .led,
  .flagship .verdict,.flagship .go{grid-column:1}
  .flagship .params{
    grid-column:2;grid-row:2/span 8;align-self:start;   /* row-gap is 0, so
                          the rows this leaves empty cost nothing */
    grid-template-columns:minmax(0,1fr);margin:0;
  }
  .flagship .go{margin-top:var(--s8)}
}

.support{list-style:none;margin:0;padding:0}
.support a{
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--s8) var(--s20);
  align-items:baseline;padding:var(--s16) 0;min-height:44px;
}
@media(min-width:760px){.support a{grid-template-columns:44px minmax(0,380px) minmax(0,1fr) auto}}
.support .idx{font-size:var(--t-label);color:var(--ink-3);display:none}
@media(min-width:760px){.support .idx{display:block}}
.support .nm{font-weight:600;font-size:var(--t-sub);letter-spacing:-.015em;transition:color .2s var(--ease)}
.support a:hover .nm{color:var(--ember)}
.support .rl{font-size:var(--t-label);color:var(--ink-3);grid-column:1/-1}
@media(min-width:760px){.support .rl{grid-column:auto}}
.support .yr{font-size:var(--t-label);color:var(--ink-3);text-align:right}

/* The four supporting accounts as cards: the flagship's own card, one level
   quieter — same edge, same raised ground, same ember on hover — so the two
   sections read as one family and the flagships still lead. The markup is
   unchanged; only the placement is. Rows stay the rows on the 404 page. */
.support.cards{display:grid;gap:var(--s16);grid-template-columns:minmax(0,1fr)}
@media(min-width:760px){.support.cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
.support.cards li{min-width:0}
.support.cards a{
  display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--s8) var(--s12);
  align-content:start;height:100%;padding:var(--f22-32);
  border:1px solid var(--edge);background:var(--raised);
  transition:border-color var(--dur-2) var(--ease);
}
.support.cards a:hover,.support.cards a:focus-visible{border-color:var(--ember)}
.support.cards a:active{box-shadow:inset 0 0 0 2px var(--ember)}
.support.cards .idx{display:block;grid-column:1;grid-row:1}
.support.cards .yr{grid-column:2;grid-row:1;text-align:right}
.support.cards .nm{grid-column:1/-1;grid-row:2;font-size:var(--t-sub);line-height:1.2}
.support.cards .rl{grid-column:1/-1;grid-row:3;max-width:34ch}

.coming-projects{
  margin:var(--f26-40) 0 0;padding:var(--f22-32);
  border:1px solid var(--edge);background:var(--raised);
  color:var(--ink-2);font-size:var(--t-body);
}


/* ---------- closing block and footer -------------------------- */
.close .wrap{padding-top:var(--f38-86);padding-bottom:var(--f30-52)}
/* The page ends on its centre line: the invitation and the two ways to
   answer it, stacked and centred — the one place the site stops running off
   its left margin, because nothing follows it. */
.close .wrap{text-align:center}
.close h2{
  font-weight:700;font-size:var(--t-close);letter-spacing:-.035em;
  line-height:1.06;margin:0 auto var(--f22-32);max-width:16ch;
}
.close p{color:var(--ink-2);margin:0 auto var(--f22-32);max-width:48ch;font-size:var(--t-body)}
.close .links{display:flex;flex-wrap:wrap;gap:var(--s4) var(--s32);justify-content:center}
.close .links a{
  display:inline-flex;align-items:center;gap:var(--s8);min-height:44px;font-size:var(--t-body);
  border-bottom:1px solid transparent;
  transition:border-color var(--dur-2) var(--ease),color var(--dur-2) var(--ease);
}
.close .links a:hover{color:var(--ember);border-color:var(--ember)}
.foot .wrap{padding-top:var(--s16);padding-bottom:var(--s32);display:flex;justify-content:center;flex-wrap:wrap;gap:var(--s8)}

/* ---------- reveal -------------------------------------------- */
/* Visible by default: without JavaScript nothing is ever hidden. The
   hidden state is only armed once the document is marked as scripted. */
.rev{opacity:1;transform:none}
html.js .rev{opacity:0;transform:translateY(16px)}
html.js .rev.in{opacity:1;transform:none;transition:opacity var(--dur-3) var(--ease),transform var(--dur-3) var(--ease)}
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  .rev{opacity:1!important;transform:none!important;transition:none!important}
  *{transition-duration:.01ms!important;animation:none!important}
}

/* ---------- language switch ----------------------------------- */
/* A site-language switch, not a page translation: where a page has a
   counterpart it goes there, otherwise to that language's home. */
.lang{display:inline-flex;align-items:center;gap:2px;margin-left:var(--s8)}
.lang a{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;min-width:42px;
  font-size:var(--t-label);letter-spacing:.01em;
  color:var(--ink-3);transition:color var(--dur-1) var(--ease);
}
.lang a:hover{color:var(--ink)}
.lang a[aria-current]{color:var(--ink)}         /* same rule, same bar. Ember stays for actions */
.panel .lang{display:flex;margin-top:var(--s16);padding-top:var(--s8)}
.panel .lang a{min-height:48px;border-bottom:0;font-size:var(--t-label)}

/* ---------- the product's own logotype ------------------------- */
/* bugreports carries a full stop in the accent colour: it is part of
   the name, not punctuation, so it is hidden from screen readers. */
.bd{color:var(--ember)}

/* ---------- the device ---------------------------------------- */
/* An iPhone 17 Pro, drawn rather than photographed. Every number here
   comes from Apple's published measurements: a body of 71.9 x 150.0 mm,
   a 6.3-inch screen of 66.59 x 144.78 mm (1206 x 2622 px at 460 ppi,
   402 x 874 points), which leaves a bezel of 2.6 mm on all four sides.
   Everything inside is a share of one of those two boxes, so the frame
   is the right shape at any width and carries no image weight. */
.device{display:flex;flex-direction:column;align-items:center;gap:var(--s16);min-width:0}
.device-frame{
  /* The app inside is laid out at 402pt and scaled down to whatever this
     is drawn at, so every tap target shrinks with the frame. At 34vh on a
     900px window the scale fell to 0.70 and a 44pt button became 31px on
     screen — usable, but it did not feel it. 46vh keeps the scale near 0.9
     on a laptop and the frame still clears a short window. */
  position:relative;width:min(360px,78vw,46vh);
  aspect-ratio:719/1500;
  border-radius:17.94%/8.6%;
  background:linear-gradient(148deg,#585b63,#191b1f 34%,#3a3d44 63%,#131518);
  box-shadow:0 34px 64px rgba(0,0,0,.6),0 2px 6px rgba(0,0,0,.6),inset 0 0 0 1px rgba(255,255,255,.10);
}
/* The bezel is set with insets rather than padding on purpose: a
   percentage padding is measured against whatever contains the frame,
   so the screen came out a different shape on every page. An inset is
   measured against the frame itself, which is the only box that matters
   — 2.61 mm of the body's height above and below, 2.655 mm of its width
   left and right. The screen is also the container everything inside is
   measured against: 1cqw is a hundredth of its width, or 4.02 points. */
.device-screen{
  position:absolute;top:1.74%;right:3.693%;bottom:1.74%;left:3.693%;
  border-radius:15.42%/7.09%;overflow:hidden;background:#000;
  container-type:inline-size;
}
/* The stills are scenery, never a surface: they sit above the iframe
   so the fade works, and an element with opacity 0 still swallows every
   tap unless pointer events are turned off. This is what made the
   running demo look frozen. */
.device-screen img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:2;
  opacity:0;pointer-events:none;
  transition:opacity .5s var(--ease),visibility 0s .5s;
}
.device-screen img.is-on{opacity:1;visibility:visible}
/* Once the app itself is running the still behind it is of no further
   use, and fading it out is how the reader learns the demo has arrived. */
.device[data-running] .device-screen img{opacity:0;visibility:hidden}
/* Without JavaScript nothing toggles, so one screen is the screen. */
html:not(.js) .device-screen img{opacity:0}
html:not(.js) .device-screen img[data-theme="light"][data-first]{opacity:1}

/* ---------- the status bar ------------------------------------- */
/* The app draws under it, as it does on the phone: 62 points of safe
   area at the top, 34 at the bottom, and this strip sits over the
   app's own background. The island is the sensor housing, so it is
   black in both themes; the clock and the icons take the app's ink. */
.device-status{
  position:absolute;left:0;right:0;top:0;height:13.43cqw;z-index:3;
  display:grid;grid-template-columns:1fr 31.09cqw 1fr;align-items:center;
  color:#000;pointer-events:none;
}
[data-app-theme="dark"] .device-status{color:#fff}
.dst-time{
  justify-self:center;
  font-family:-apple-system,"SF Pro Text","Helvetica Neue",var(--sans);
  font-size:4.23cqw;font-weight:600;letter-spacing:.01em;line-height:1;
  font-variant-numeric:tabular-nums;
}
.dst-island{
  justify-self:center;align-self:start;
  width:31.09cqw;height:9.13cqw;margin-top:2.736cqw;
  background:#000;border-radius:9999px;
}
.dst-icons{justify-self:center;display:flex;align-items:center;gap:1.7cqw}
.dst-icons svg{display:block;height:auto}
.dst-cell{width:4.23cqw;fill:currentColor}
.dst-wifi{width:4.06cqw;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}
.dst-wifi .dot{fill:currentColor;stroke:none}
.dst-batt{width:6.79cqw}
.dst-batt .shell{fill:none;stroke:currentColor;stroke-width:1.2;opacity:.35}
.dst-batt .level,.dst-batt .nub{fill:currentColor}
.dst-batt .nub{opacity:.4}
/* The home indicator: 140 x 5 points, 8 above the bottom edge. */
.device-home{
  position:absolute;left:50%;transform:translateX(-50%);
  bottom:1.99cqw;width:34.83cqw;height:1.244cqw;border-radius:9999px;
  background:#000;opacity:.32;z-index:3;pointer-events:none;
}
[data-app-theme="dark"] .device-home{background:#fff;opacity:.5}

/* The phone looks like a picture of a phone until someone touches it,
   so one line above it says otherwise, with room between the two. Without JavaScript there is no
   running app to invite anyone into, and the line goes with it. */
.device-hint{
  order:-1;margin:0 0 var(--s16);max-width:34ch;text-align:center;
  font-size:var(--t-body-s);line-height:1.5;color:var(--ink-3);
}
html:not(.js) .device-hint{display:none}

.device-ctl{display:flex;align-items:center;gap:var(--s8);flex-wrap:wrap;justify-content:center}
.dbtn{
  display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;
  padding:0 var(--s12);
  background:none;border:1px solid var(--edge);color:var(--ink-2);cursor:pointer;
  font-family:var(--sans);font-size:var(--t-body-s);
  transition:color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease);
}
.dbtn:hover{color:var(--ink);border-color:var(--ink-3)}
.dbtn:focus-visible{outline:2px solid var(--ember);outline-offset:2px}
.dbtn:active{color:var(--ember);border-color:var(--ember)}
.dbtn[aria-pressed="true"]{color:var(--ink);border-color:var(--ink);background:rgba(247,247,250,.06)}

/* the app's own light/dark, switched by the reader: the only control
   under the frame, unlabelled — the buttons say what they do — and the
   app answers it while it is running. One segmented control, one border:
   the buttons themselves carry none, so the shared middle line is a
   single rule that never doubles or changes weight with the state. */
/* Two segmented switches under the phone: the app's theme, and — only where a
   second demo exists — the app's language. They sit on one line and wrap onto
   two before they would ever squeeze. */
.device-switches{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--s12)}
.theme-switch{display:flex;align-items:center;justify-content:center}
.theme-switch .seg{display:flex;border:1px solid var(--edge)}
.theme-switch .dbtn{font-size:var(--t-label);border:0}
.theme-switch .dbtn + .dbtn{border-left:1px solid var(--edge)}
.theme-switch .dbtn[aria-pressed="true"]{color:var(--ink);background:rgba(247,247,250,.08)}

/* ---------- the live demo inside the frame --------------------- */
/* The app is laid out at the phone's own 402 x 874 points and then
   scaled to whatever the frame is drawn at, so nothing is squeezed:
   the demo measures the same screen the simulator does. */
.device-demo{
  position:absolute;top:0;left:0;z-index:1;border:0;background:transparent;
  width:402px;height:874px;transform-origin:0 0;
}

/* ---------- the enlarged image -------------------------------- */
/* A shot is read at about half the width it was drawn at. Pressing one
   lifts it out onto the page's own ground at its full pixel size. The
   overlay scrolls in both directions, so enlarging never shrinks the image
   back down to the viewport. */
.zoomable{cursor:zoom-in}
.zoomable:focus-visible{outline:2px solid var(--ember);outline-offset:3px}
/* A screenshot opened on a phone is wider than the phone — that is the
   point of opening it — so the overlay is a scroll container and the image
   is panned rather than trapped. "safe center" keeps both edges reachable
   when either dimension exceeds the viewport. */
.zoom{
  position:fixed;inset:0;z-index:60;display:grid;place-items:safe center;
  padding:var(--f22-32);background:rgba(3,3,4,.92);
  overflow:auto;overscroll-behavior:contain;
  touch-action:pan-x pan-y pinch-zoom;
  -webkit-overflow-scrolling:touch;
}
.zoom img{
  display:block;max-width:none;max-height:none;
  width:auto;height:auto;
  border:1px solid var(--rule);background:var(--raised);
}
/* Desktops keep the complete screenshot inside the viewport. Phones retain
   the full designed size and use the overlay's native pan/scroll behaviour. */
@media (min-width:700px){
  .zoom{overflow:hidden}
  .zoom img{
    height:auto !important;
    max-width:calc(100vw - 64px) !important;
    max-height:calc(100vh - 64px) !important;
    object-fit:contain;
  }
}
/* fixed, not absolute: the way out must not scroll away with the picture */
.zoom-x{
  position:fixed;top:var(--s16);right:var(--s16);z-index:1;
  min-height:44px;padding:0 var(--s16);
  /* it sits over the picture now, which can be white: its own ground */
  background:rgba(3,3,4,.88);color:var(--ink);border:1px solid var(--edge);
  font:inherit;font-size:var(--t-body-s);cursor:pointer;
  transition:color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease);
}
.zoom-x:hover,.zoom-x:focus-visible{color:var(--ember);border-color:var(--ember);outline:none}
@media (prefers-reduced-motion: reduce){.zoom,.zoom img{animation:none}}
