/* Components
   Lifted verbatim from "14 Website prototype.dc.html".
   Prototype lines 66-84 and 100-414, in source order. The reduced-motion block stays last. */

.px{position:relative;overflow:hidden;isolation:isolate;display:inline-flex;align-items:center;min-height:var(--target-min);font:var(--type-ui);letter-spacing:var(--track-ui);text-transform:uppercase;white-space:nowrap;flex:none;background:none;border-radius:0;cursor:pointer}
.px > i{position:absolute;inset-block-start:calc(50% - var(--px-half));inset-inline-start:var(--px-inset);width:var(--px-size);height:var(--px-size);background:var(--px-mark);transform-origin:50% 50%;transition:transform var(--dur-pixel) var(--ease-in-out);z-index:-1}
.px > span{position:relative;transition:color var(--dur-pixel) var(--ease-in-out)}
@media (hover:hover){.px:hover > i{transform:scale(var(--px-scale))}.px:hover > span{color:var(--px-ink)}}
.px:active > i{background:var(--px-pressed,var(--px-mark))}

.px,.fdfil button,.vtoggle,.card,.vmedia,.vname,.namerun b,.band,.efeat{
  transition-property:transform;transition-duration:var(--dur-release);transition-timing-function:var(--ease-release)}
.px:active,.fdfil button:active,.card:active{transform:scale(var(--press-deep));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
/* Whole-band links. Soft press: at 660px tall a deep scale reads as the page
   moving rather than the target acknowledging. */
.band:active,.efeat:active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
.vtoggle:active{transform:scale(var(--press-deep));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
.vrow[data-open="1"] .vtoggle:active{transform:rotate(45deg) scale(var(--press-deep))}
.vname:active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
.vmedia:active .photo,.card:active .photo{transform:scale(1.03);transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
.vmedia .photo,.card .photo{transition:transform var(--dur-release) var(--ease-release)}
@media (prefers-reduced-motion:reduce){.px,.fdfil button,.vtoggle,.card,.vmedia,.vname,.vmedia .photo,.card .photo,.band-media .photo,.band-media .swap,.band,.efeat{transition:none}
.px:active,.fdfil button:active,.card:active,.vtoggle:active,.vname:active,.vmedia:active .photo,.card:active .photo,.band:active,.efeat:active{transform:none}}

.photo,.swap{position:absolute;inset:0;background-size:cover;background-position:center}
.shot{position:relative;overflow:hidden;background:var(--media-ground)}
.qa{border-block-start:var(--hairline) solid var(--rule)}
.qa summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:var(--space-5);min-height:var(--target-min);padding-block:var(--space-4);font:var(--type-title);letter-spacing:var(--track-title);text-transform:uppercase;transition:color var(--dur-micro) var(--ease-out)}
.qa summary::-webkit-details-marker{display:none}
.qa summary:hover{color:var(--accent-ink)}
.qa summary:focus-visible{outline:var(--focus-width) solid var(--terracotta);outline-offset:var(--focus-offset)}
.qa-mark{position:relative;width:12px;height:12px;flex:none}
.qa-mark::before,.qa-mark::after{content:'';position:absolute;background:var(--accent-ink);transition:transform var(--dur-hover) var(--ease-in-out),opacity var(--dur-hover) var(--ease-in-out)}
.qa-mark::before{inset-block-start:5px;inset-inline:0;height:2px}
.qa-mark::after{inset-inline-start:5px;inset-block:0;width:2px}
.qa[open] .qa-mark::after{transform:rotate(90deg);opacity:0}
.qa[open] summary{color:var(--accent-ink)}
.role{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,3fr) minmax(0,2fr) auto;gap:var(--gutter);align-items:baseline;border-block-start:var(--hairline) solid var(--rule);padding-block:var(--space-5);color:var(--ink);min-height:var(--target-min);transition:background var(--dur-micro) var(--ease-out),padding-inline var(--dur-hover) var(--ease-out)}
.role{transition-property:background,padding-inline,transform;transition-duration:var(--dur-hover),var(--dur-hover),var(--dur-release);transition-timing-function:var(--ease-out),var(--ease-out),var(--ease-release)}
@media (hover:hover){.role:hover{background:var(--rule);padding-inline:var(--space-4)}}
.role:active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
.role-go{display:inline-flex;align-items:center;gap:var(--space-3);font:var(--type-ui);letter-spacing:var(--track-ui);text-transform:uppercase;color:var(--accent-ink);justify-self:end}
.role-go > i{width:8px;height:8px;background:var(--accent-ink);transition:transform var(--dur-hover) var(--ease-out)}
@media (hover:hover){.role:hover .role-go > i{transform:translateX(8px)}}
@media (max-width:1023px){.role{grid-template-columns:minmax(0,1fr) auto;row-gap:var(--space-2)}.role .cap{grid-column:1}}
.hire{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--gutter)}
@media (max-width:1023px){.hire{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){.hire{grid-template-columns:minmax(0,1fr)}}
.press{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gutter)}
@media (max-width:1023px){.press{grid-template-columns:minmax(0,1fr)}}
.press-card{display:flex;flex-direction:column;border:var(--hairline) solid var(--rule-strong);padding:var(--space-6);color:var(--ink);min-height:200px;transition:border-color var(--dur-micro) var(--ease-out),transform var(--dur-release) var(--ease-release)}
.press-card:active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
@media (hover:hover){.press-card:hover{border-color:var(--ink)}}
.press-go{margin-block-start:auto;padding-block-start:var(--space-5);font:var(--type-ui);letter-spacing:var(--track-ui);text-transform:uppercase;color:var(--accent-ink)}
.cov{display:grid;grid-template-columns:120px minmax(0,1fr) 160px;gap:var(--gutter);align-items:baseline;border-block-start:var(--hairline) solid var(--rule);padding-block:var(--space-4);color:var(--ink);min-height:var(--target-min);transition:color var(--dur-micro) var(--ease-out),transform var(--dur-release) var(--ease-release)}
.cov:active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
@media (hover:hover){.cov:hover{color:var(--accent-ink)}}
@media (max-width:560px){.cov{grid-template-columns:minmax(0,1fr);row-gap:var(--space-2)}.cov .cap:last-child{text-align:start}}
@media (max-width:1023px){.panel{grid-template-columns:minmax(0,1fr)}.crow{grid-template-columns:minmax(0,1fr);row-gap:var(--space-3)}}
.ticker{overflow:hidden;border-block:var(--hairline) solid var(--rule);padding-block:var(--space-4);display:flex;gap:0;white-space:nowrap}
.ticker > span{font:var(--type-display-md);letter-spacing:var(--track-display);text-transform:uppercase;flex:none;display:flex;gap:var(--space-8);padding-inline-end:var(--space-8);align-items:center;animation:tick 34s linear infinite;animation-duration:var(--tick-dur,34s)}
.ticker em{font-style:normal;color:var(--accent-ink)}
.ticker:hover > span{animation-play-state:paused}
@keyframes tick{from{transform:translateX(0)}to{transform:translateX(-100%)}}
@keyframes rise{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:translateY(0)}}
@keyframes drift{from{transform:translateY(-6%) scale(1.12)}to{transform:translateY(6%) scale(1.12)}}
@supports (animation-timeline: view()){
  .rv{animation:rise auto var(--ease-out) both;animation-timeline:view();animation-range:entry 10% entry 62%}
  .shot > .photo{animation:drift auto linear both;animation-timeline:view();animation-range:cover 0% cover 100%}
  .card:hover .shot > .photo,.card .shot > .swap{animation:none}
}
@media (prefers-reduced-motion: reduce){
  .ticker > span{animation:none}
  .rv,.shot > .photo{animation:none!important;opacity:1;transform:none}
}
.ed{display:grid;grid-template-columns:minmax(0,6fr) minmax(0,6fr);gap:var(--space-9);align-items:center;padding-block:var(--space-9);border-block-start:var(--hairline) solid var(--rule)}
.ed-media{position:relative;overflow:hidden;background:var(--media-ground);aspect-ratio:var(--ar-wide)}
.ed-media .photo{transition:transform var(--dur-hover) var(--ease-out)}
@media (hover:hover){.ed:hover .ed-media .photo{transform:scale(1.03)}}
.ed-n{font:300 clamp(60px,7vw,120px)/0.82 var(--font-display);letter-spacing:var(--track-display-xl);color:var(--rule-strong);display:block;margin-block-end:var(--space-4)}
@media (max-width:1023px){.ed{grid-template-columns:minmax(0,1fr);gap:var(--space-6);padding-block:var(--space-7)}.ed-media{order:-1!important}}
.fd-plate{position:relative;height:min(88svh,880px);overflow:hidden;background:var(--media-ground)}
.fd-plate .photo{position:absolute;inset:0;background-size:cover;background-position:center 58%}
.fd-veil{position:absolute;inset:0;background:linear-gradient(to bottom,rgba(34,34,35,.52) 0%,rgba(34,34,35,.12) 40%,rgba(34,34,35,.78) 100%)}
.fd-plate-type{position:absolute;inset-inline:var(--margin);inset-block-end:var(--space-8);color:var(--cream)}

.feat{display:grid;grid-template-columns:minmax(0,6fr) minmax(0,6fr);min-height:min(84svh,860px)}
.feat-media{position:relative;overflow:hidden;background:var(--media-ground)}
.feat-media .photo{position:absolute;inset:-6% 0;background-size:cover;background-position:center}
@supports (animation-timeline: view()){.feat-media .photo{animation:drift linear both;animation-timeline:view();animation-range:entry 0% exit 100%}}
.feat-body{display:flex;flex-direction:column;justify-content:center;padding:var(--section-block) var(--margin)}
.feat[data-flip="1"] .feat-media{order:2}
.feat-num{font:300 clamp(56px,7vw,120px)/0.82 var(--font-display);letter-spacing:var(--track-display-xl);color:var(--rule-strong);display:block}
@media (max-width:1023px){.feat{grid-template-columns:minmax(0,1fr);min-height:0}.feat[data-flip="1"] .feat-media{order:0}.feat-media{aspect-ratio:var(--ar-card);min-height:0}}


.fdfil{display:flex;flex-wrap:nowrap;align-items:stretch;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;border-block:var(--hairline) solid var(--rule-strong);margin-inline:var(--margin)}
.fdfil::-webkit-scrollbar{display:none}
.fdfil button{display:flex;flex:none;white-space:nowrap;align-items:center;gap:var(--space-3);min-height:64px;padding-inline:var(--space-5);background:none;border:0;border-inline-end:var(--hairline) solid var(--rule);cursor:pointer;font:var(--type-ui);letter-spacing:var(--track-ui);text-transform:uppercase;color:var(--ink-muted);transition:color var(--dur-micro) var(--ease-out),background var(--dur-micro) var(--ease-out),transform var(--dur-release) var(--ease-release)}
.fdfil button i{width:8px;height:8px;flex:none;background:var(--rule-strong);transition:background var(--dur-micro) var(--ease-out),transform var(--dur-micro) var(--ease-out)}
.fdfil button[aria-pressed="true"]{color:var(--ink)}
.fdfil button[aria-pressed="true"] i{background:var(--accent-ink);transform:rotate(45deg)}
@media (hover:hover){.fdfil button:hover{color:var(--ink);background:var(--surface-wash)}.fdfil button:hover i{background:var(--accent-ink)}}
/* Ten chips need 1817px and never had it. Even at a 1920 viewport the last one
   was cut off, and .fdfil hides its own scrollbar, so nothing on screen said
   there was more -- "the full line-up doesn't show properly", 14 September.

   From 768 up they wrap, so every chip is reachable without a swipe. Below 768
   wrapping would cost eight rows and 514px of filters above the kitchens, so
   the phone keeps the swipeable row, which is the familiar pattern on touch. */
@media (min-width:768px){.fdfil{flex-wrap:wrap;overflow-x:visible}}

/* "I need the filter to be all on same line but the fonts are readable."
   Measured: 91px of every chip was overhead before a single letter -- 48 of
   padding, 11 of marker, 24 of gaps, 8 of count -- against 907px of actual
   text. So the overhead gives way and the 12px type does not. Ten chips come
   to 1312px, inside the 1345 a 1440 viewport leaves. The marker and the counts
   both survive; only the air around them goes. */
@media (min-width:1440px){
  .fdfil{flex-wrap:nowrap;overflow-x:visible}
  /* 8px, not the 10 the arithmetic suggested: a 1440 window carries a scrollbar
     and the last chip still clipped by 31px when measured on the built page. */
  .fdfil button{padding-inline:8px;gap:4px;letter-spacing:.7px}
  .fdfil button i{width:6px;height:6px}
}

@keyframes rowin-a{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}
@keyframes rowin-b{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}
.vrow{animation-duration:var(--dur-hover);animation-timing-function:var(--ease-out);animation-fill-mode:both}
.vrow[data-anim="a"]{animation-name:rowin-a}
.vrow[data-anim="b"]{animation-name:rowin-b}
.vrow:nth-child(1){animation-delay:0ms}.vrow:nth-child(2){animation-delay:50ms}.vrow:nth-child(3){animation-delay:100ms}
.vrow:nth-child(4){animation-delay:150ms}.vrow:nth-child(5){animation-delay:200ms}.vrow:nth-child(6){animation-delay:250ms}
.vrow:nth-child(7){animation-delay:300ms}.vrow:nth-child(8){animation-delay:350ms}.vrow:nth-child(9){animation-delay:400ms}
.vrow{display:grid;grid-template-columns:44px minmax(0,1fr) 200px;gap:var(--gutter);align-items:start;border-block-start:var(--hairline) solid var(--rule);padding-block:var(--space-5);transition:grid-template-columns var(--dur-unfold) var(--ease-unfold)}
.vrow[data-open="1"]{grid-template-columns:44px minmax(0,1fr) 560px}
.vtoggle{position:relative;width:44px;height:44px;display:grid;place-items:center;border:var(--hairline) solid var(--rule-strong);background:none;cursor:pointer;color:var(--ink);transition:transform var(--dur-unfold) var(--ease-unfold),border-color var(--dur-micro) var(--ease-out),background var(--dur-micro) var(--ease-out)}
.vtoggle b{position:absolute;background:currentColor}
.vtoggle b:first-child{width:14px;height:1.5px}
.vtoggle b:last-child{width:1.5px;height:14px}
.vrow[data-open="1"] .vtoggle{transform:rotate(45deg);border-color:var(--accent-ink);color:var(--accent-ink)}
@media (hover:hover){.vtoggle:hover{border-color:var(--accent-ink);color:var(--accent-ink)}}
.vname{font:var(--type-display-lg);letter-spacing:var(--track-display-xl);text-transform:uppercase;color:var(--ink);display:inline-flex;align-items:center;min-height:var(--target-min);transition:color var(--dur-micro) var(--ease-out),transform var(--dur-release) var(--ease-release)}
@media (hover:hover){.vname:hover{color:var(--accent-ink)}}
.vmedia{position:relative;display:block;overflow:hidden;background:var(--media-ground);height:150px;transition:height var(--dur-unfold) var(--ease-unfold),transform var(--dur-release) var(--ease-release)}
.vrow[data-open="1"] .vmedia{height:440px}
.vmedia .photo{position:absolute;inset:0;background-size:cover;background-position:center;transition:transform var(--dur-signature) var(--ease-out)}
.vbody{position:relative;overflow:hidden;max-height:7.4em;transition:max-height var(--dur-unfold) var(--ease-unfold)}
.vrow[data-open="1"] .vbody{max-height:56em}
.vbody::after{content:"";position:absolute;inset-inline:0;inset-block-end:0;height:3.6em;background:linear-gradient(180deg,transparent 0%,var(--surface) 86%);opacity:1;transition:opacity var(--dur-unfold) var(--ease-unfold);pointer-events:none}
.vrow[data-open="1"] .vbody::after{opacity:0}
@media (max-width:1023px){.vrow,.vrow[data-open="1"]{grid-template-columns:44px minmax(0,1fr)}.vmedia{grid-column:1/-1;height:220px}.vrow[data-open="1"] .vmedia{height:420px}}
@media (max-width:767px){.vmedia{height:180px}.vrow[data-open="1"] .vmedia{height:320px}}
@media (prefers-reduced-motion:reduce){.vrow,.vmedia,.vbody,.vbody::after,.vtoggle,.vlist,.feat-media .photo{transition:none;animation:none}}
.namerun{overflow:hidden;display:flex;gap:0;white-space:nowrap;padding-block:var(--space-6);border-block:var(--hairline) solid var(--rule)}
.namerun > span{flex:none;display:flex;align-items:center;gap:var(--space-8);padding-inline-end:var(--space-8);animation:tick 46s linear infinite}
.namerun b{font:300 clamp(20px,2.1vw,34px)/1 var(--font-display);letter-spacing:var(--track-display-xl);text-transform:uppercase;font-weight:300;color:var(--ink);transition:color var(--dur-micro) var(--ease-out),transform var(--dur-release) var(--ease-release)}
.namerun i{width:6px;height:6px;background:var(--accent-ink);flex:none}
/* Kitchen marks. Each is a single-colour silhouette painted with the ground's
   own ink through a mask, so one file is correct on cream and on black and no
   tenant's brand palette fights the section it is standing in. Height is fixed
   and width follows the mark's own ratio, which runs from square to nearly ten
   to one -- that is how a logo strip keeps optical weight even.

   The name renders unless masks are supported, so a browser without them keeps
   the wordmark strip rather than showing nine solid rectangles. */
.vendor-mark{display:none}
@supports ((mask-image:url('')) or (-webkit-mask-image:url(''))){
  .namerun b.mark-name{display:none}
  .namerun .vendor-mark{
    display:block;flex:none;
    --mark-h:calc(clamp(22px,2.4vw,38px) * var(--mark-scale,1));
    height:var(--mark-h);width:calc(var(--mark-h) * var(--mark-ratio,4));
    background-color:currentColor;
    -webkit-mask-image:var(--mark-src);mask-image:var(--mark-src);
    -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
    -webkit-mask-position:center;mask-position:center;
    -webkit-mask-size:contain;mask-size:contain;
    opacity:.78;
    transition-property:opacity,background-color,transform;
    transition-duration:var(--dur-micro);transition-timing-function:var(--ease-out)}
}
@media (hover:hover){.namerun .vendor-mark:hover{opacity:1;background-color:var(--accent-ink)}}
.namerun-go:active .vendor-mark{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
@media (prefers-reduced-motion:reduce){.namerun .vendor-mark{transition-duration:0s}}
.namerun:hover > span{animation-play-state:paused}
.namerun-go:active b{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
/* Each mark is its own link now, so the press and the hover belong to the mark
   that was pressed rather than to the whole strip. */
.namerun-go{display:flex;align-items:center;justify-content:center;min-height:var(--target-min);min-width:var(--target-min);padding-block:var(--space-2);color:inherit;text-decoration:none;transition-property:transform;transition-duration:var(--dur-release);transition-timing-function:var(--ease-release)}
.namerun-go:focus-visible{outline:var(--focus-width) solid var(--accent-ink);outline-offset:var(--focus-offset)}
.namerun{transition:transform var(--dur-release) var(--ease-release)}
@media (hover:hover){.namerun b:hover{color:var(--accent-ink)}}
.krow{display:grid;grid-template-columns:52px auto minmax(0,5fr) minmax(0,3fr) minmax(0,3fr) auto;gap:var(--gutter);align-items:center;border-block-start:var(--hairline) solid var(--rule);padding-block:var(--space-5);color:var(--ink);min-height:76px}
.kthumb{width:0;aspect-ratio:var(--ar-tile);overflow:hidden;background:var(--media-ground);transition:width var(--dur-hover) var(--ease-out)}
@media (hover:hover){.krow:hover .kthumb{width:96px}.krow:hover .kname{color:var(--accent-ink)}}
.krow:focus-visible .kthumb{width:96px}
.kname{font:var(--type-display-md);letter-spacing:var(--track-display);text-transform:uppercase;transition:color var(--dur-micro) var(--ease-out)}
.kstate{display:inline-flex;align-items:center;gap:var(--space-3);font:var(--type-eyebrow);letter-spacing:var(--track-eyebrow);text-transform:uppercase;justify-self:end;white-space:nowrap}
.kstate em{width:8px;height:8px;background:currentColor;font-style:normal;flex:none}
@media (max-width:1023px){.krow{grid-template-columns:44px minmax(0,1fr) auto;row-gap:var(--space-2)}.kthumb{display:none}.krow .cap{grid-column:2}}
.band{display:grid;grid-template-columns:minmax(0,6fr) minmax(0,6fr);align-items:stretch;min-height:min(74svh,660px)}
.band-media{position:relative;overflow:hidden;background:var(--media-ground)}
/* The zone band emits a second photograph the same way a card does, but until
   now nothing ever hid it: .photo and .swap are both position:absolute, so the
   swap simply sat on top and the hero was never visible. The band therefore had
   no cross-fade at all, and "change the zone's image" could only be answered by
   changing the hover frame. Found on 11 September by reading the live capture,
   not the stylesheet -- both layers computed to opacity 1 with the swap loaded.
   Same shape as .card .shot, in longhands so transform stays in
   transition-property. */
.band-media .photo,.band-media .swap{transition-property:transform,opacity;transition-duration:var(--dur-hover);transition-timing-function:var(--ease-out)}
.band-media .swap{opacity:0}
@media (hover:hover){
  .band:hover .band-media .photo{transform:scale(1.03)}
  .band:hover .band-media .swap{opacity:1;transform:scale(1.03)}
}
.band-body{display:flex;flex-direction:column;justify-content:center;gap:var(--space-5);padding:var(--space-9) var(--margin)}
.band-stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-5);border-block-start:var(--hairline) solid var(--rule);padding-block-start:var(--space-5)}
.band-stat b{display:block;font:300 32px/1 var(--font-display);letter-spacing:var(--track-display-xl);font-weight:300}
@media (max-width:1023px){.band{grid-template-columns:minmax(0,1fr);min-height:0}.band-media{aspect-ratio:var(--ar-wide);order:-1!important}.band-body{order:1!important}.band-body{padding:var(--space-7) var(--margin) var(--space-8)}}
.vrun{display:grid;grid-template-columns:minmax(0,4fr) minmax(0,8fr);gap:var(--space-9);border-block-start:var(--hairline) solid var(--rule);padding-block:var(--space-8);min-height:46svh}
.vrun-n{position:sticky;inset-block-start:calc(var(--bar-h) + var(--space-7));align-self:start}
.vrun-n b{display:block;font:300 clamp(64px,8vw,132px)/0.82 var(--font-display);letter-spacing:var(--track-display-xl);font-weight:300;color:var(--accent-ink)}
.vrun-shot{position:relative;overflow:hidden;background:var(--media-ground);aspect-ratio:var(--ar-wide);margin-block-start:var(--space-6)}
@media (max-width:1023px){.vrun{grid-template-columns:minmax(0,1fr);gap:var(--space-5);min-height:0;padding-block:var(--space-7)}.vrun-n{position:static}.vrun-n b{font-size:56px}}
.pxbar{--px-size:8px;--px-half:4px;--px-inset:var(--space-4);--px-scale:70;--px-mark:var(--cream);--px-ink:var(--black);padding-inline:var(--space-7) var(--space-5);color:var(--cream);border:none}
/* The switch names the other language in that language's own script, so it wears
   that script's face rather than the Latin UI face .px would hand it. On the Arabic
   site the label is "English" and the UI face is the right one again. */
.bar-lang{font:600 15px/1.2 var(--font-ar);letter-spacing:0}
[dir="rtl"] .bar-lang{font:var(--type-ui);letter-spacing:var(--track-ui)}
/* The bar CTA's two labels. See parts/header-bar.php: the switch does not fit
   beside the long one on a phone. */
.bar-cta-short{display:none}
/* 639, not the 560 the padding step uses: at 561 the long label came back with
   6px of slack, which is inside the margin font loading moves things by. */
@media (max-width:639px){.bar-cta-long{display:none}.bar-cta-short{display:inline}}
.pxprimary{--px-size:12px;--px-half:6px;--px-inset:var(--space-5);--px-scale:90;padding-inline:var(--space-8) var(--space-5);border:var(--hairline) solid currentColor}
.pxsecondary{--px-size:10px;--px-half:5px;--px-inset:var(--space-5);--px-scale:80;padding-inline:var(--space-8) var(--space-5);border:var(--hairline) solid currentColor}
.pxtertiary{--px-size:10px;--px-half:5px;--px-inset:0;--px-scale:80;padding-inline:var(--space-6) var(--space-4);border:none}
/* A label carrying a brand name cannot promise to stay on one line -- the
   longest is "Visit El Ta'koy Hawaiian Street Food", which is wider than a
   390px screen. Wrapping beats a horizontal scrollbar, and the target keeps
   its height because .px sets a min-height rather than a fixed one. */
.px-wrap{white-space:normal;max-width:100%}
.px-wrap > span{text-wrap:pretty}
.pxchip{--px-size:8px;--px-half:4px;--px-inset:var(--space-3);--px-scale:60;padding-inline:var(--space-7) var(--space-4);gap:var(--space-3)}

.bar{position:fixed;inset-block-start:0;inset-inline:0;height:var(--bar-h);z-index:30;display:flex;align-items:center;justify-content:space-between;padding-inline:var(--margin);background:var(--black);border-block-end:var(--hairline) solid var(--rule-accent)}
.bar-home{background-color:rgba(34,34,35,0);border-block-end-color:rgba(214,210,196,0)}
.bar-group{display:flex;border:var(--hairline) solid var(--rule-strong-accent)}
.bar-group > .px + .px{border-inline-start:var(--hairline) solid var(--rule-strong-accent)}
.bar-home-link{display:inline-flex;align-items:center;justify-content:center;min-width:var(--target-min);min-height:var(--target-min);margin-inline-start:calc((var(--target-min) - var(--icon-land)) / -2);transition:transform var(--dur-release) var(--ease-release)}
.bar-home-link:active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
/* The wordmark inside the open menu, now a home link. Longhands, so the press
   transform survives -- the shorthand above it predates the rule. */
.menu-home-link{display:inline-flex;align-items:center;min-height:var(--target-min);transition-property:transform;transition-duration:var(--dur-release);transition-timing-function:var(--ease-release)}
.menu-home-link:active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
.bar-icon{width:var(--icon-land);height:var(--icon-land);flex:none}
.bar-home .bar-icon{visibility:hidden}
@media (max-width:560px){.bar-group > .px{padding-inline:var(--space-6) var(--space-3)}}

.menu{position:fixed;inset:0;z-index:40;background:var(--cream);color:var(--black);display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);overflow-y:auto}
.menu-left{padding:var(--space-7) var(--margin);display:flex;flex-direction:column;justify-content:space-between;gap:var(--space-7)}
.menu-row{display:flex;align-items:baseline;gap:var(--space-5);padding-block:var(--space-3);border-block-start:var(--hairline) solid var(--rule-cream);width:100%;text-align:start;transition:color var(--dur-micro) var(--ease-out),transform var(--dur-release) var(--ease-release)}
.menu-row:active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
.menu-row .n{font:var(--type-eyebrow);letter-spacing:var(--track-eyebrow);color:var(--ink-muted-cream);width:28px;flex:none}
.menu-row .l{font:var(--type-display-lg);letter-spacing:var(--track-display);text-transform:uppercase}
.menu-row .m{font:var(--type-caption);color:var(--ink-muted-cream);margin-inline-start:auto}
@media (hover:hover){.menu-row:hover{color:var(--terracotta-ink-cream)}.menu-row:hover .m{color:var(--terracotta-ink-cream)}}
@media (max-width:1023px){.menu{grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto}.menu-left{padding-block:var(--space-6)}.menu-row .l{font:var(--type-display-md);letter-spacing:var(--track-display)}.menu-row .m{display:none}}

.overture{position:relative;height:var(--ov-frame);view-timeline:--ov block}
/* ovShrink lifts .ov-inner off its own frame, so .ov-media is what shows in the
   margin it opens. Named rather than left transparent: the scrim above it is
   only 72-86% opaque, so an unpainted frame lets whatever the page ground
   happens to be wash through the gutter. */
.ov-media{position:sticky;inset-block-start:0;height:100svh;overflow:hidden;background:var(--black)}
.ov-inner{position:absolute;inset:0;transform-origin:50% 50%}
.ov-inner .photo{width:100%;height:100%;background-size:cover;background-position:center 40%}
.ov-scrim{position:absolute;inset:0;background:linear-gradient(to bottom,rgba(34,34,35,.72) 0%,rgba(34,34,35,.22) 26%,rgba(34,34,35,.58) 64%,rgba(34,34,35,.86) 100%)}
.ov-scrim::before{content:'';position:absolute;inset-block-start:0;inset-inline-start:0;inset-block-end:0;inset-inline-end:0;background:var(--black);opacity:0;pointer-events:none}
.logo-block{position:fixed;inset-inline-start:var(--margin);inset-block-start:var(--arr-top);z-index:31;display:flex;align-items:center;gap:var(--logo-gap);transform-origin:0 0;pointer-events:none;opacity:var(--logo-veil)}
.logo-icon{width:var(--logo-icon);height:var(--logo-icon);flex:none}
.logo-word{width:var(--word-w);height:auto;flex:none}
/* The home page's H1, a client line added 2 Oct. The lockup owns the bottom
   edge, so the line sits a step above it, measured from the first screen of
   the overture. It scrolls with the page rather than pinning with the frame,
   so it outruns the rising lockup instead of meeting it, and ovTitle fades it
   over the first 30svh so it is gone before it reaches the bar. That fade runs
   on scroll(root), not --ov: html's scroll-padding shifts --ov's contain range
   by a bar height, so at scroll 0 that timeline is already 4-7% in, which
   would start the fade before anyone scrolls. .ov-title takes the entrance and
   .ov-head the scroll, for the same reason .ov-word wraps .logo-word. */
.ov-title{position:absolute;inset-inline:var(--margin);inset-block-end:calc(100% - 100svh + var(--arr-gap) + var(--block-h) + var(--space-6))}
.ov-head{max-width:20ch;text-wrap:balance}
.slide-wrap{position:relative;height:100svh;overflow:clip;clip-path:inset(0)}
.slide{position:fixed;inset:0;display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr)}
.slide-text{position:relative;z-index:1;display:flex;flex-direction:column;justify-content:center;padding-block:var(--space-8);padding-inline:var(--margin) var(--space-7)}
.slide-media{position:relative;justify-self:center;align-self:center;width:min(100%,var(--media-w));aspect-ratio:var(--mark-ar);overflow:hidden;background:var(--media-ground);clip-path:var(--mark)}
.slide-count{font:300 clamp(54px,6.4vw,112px)/0.86 var(--font-display);letter-spacing:var(--track-display-xl)}
.slide-unit{font:var(--type-display-md);letter-spacing:var(--track-display);text-transform:uppercase}
.slide-head{font:var(--type-display-lg);letter-spacing:var(--track-display);text-transform:uppercase;margin:var(--space-4) 0;max-width:20ch;text-wrap:pretty}
.slide-body{font:var(--type-body);max-width:36ch;text-wrap:pretty}
/* The slide's one link. A tertiary sits under a paragraph with no border to
   hold it off the copy, so the air has to come from the margin. Its marker
   lands on the text column's inline start, which is how every other
   tertiary on the site meets the copy above it. */
.slide-go{margin-block-start:var(--space-6);display:flex}
/* The pinned slide is fixed to the viewport, so its box followed the phone's
   URL bar: collapsing the bar made the slide 60px taller and the diamond grew
   with it, then shrank again on the way back. Measured at 60px on every slide.
   The slide is now sized in svh, which is the viewport with the bar showing and
   does not move while scrolling, and the wrapper is given the large viewport
   height and the same ground, so the strip the collapsing bar uncovers is the
   colour of the slide sitting on it rather than a seam. lvh is ignored by
   browsers that do not know it, which leaves them on the svh line above. */
@media (max-width:1023px){
  /* The slide stays fixed, so the chapters reveal as the wrapper's clip moves
     over them, which is the composition the desktop runs and what the phone
     should match. Only the height changes: 100svh instead of the fixed inset
     stretching to whatever the URL bar leaves, which is what made the diamond
     grow and shrink while scrolling. */
  .slide{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto;height:100svh}
  .slide-wrap{height:100svh;height:100lvh}
}
/* On a phone the mark leads and the copy follows it. The mark cannot be a
   fixed box here: at 390x745 -- a real iPhone with its browser chrome, not the
   844 a desktop emulator reports -- a 300px square plus the text column runs
   66px past the screen, so the square climbed under the fixed bar and the
   longest slide lost its top corner off the viewport entirely. Height-first
   against its own row, with the bar's height reserved above it, keeps the
   whole diamond on screen at every phone size and still caps at --media-w
   where there is room. */
@media (max-width:560px){
  .slide{padding-block-start:calc(var(--bar-h) + var(--space-4));row-gap:var(--space-5)}
  .slide-text{padding:0 var(--margin) var(--space-7)}
  /* One size for every chapter, and the same size in both languages.

     The previous rule sized the mark from the row it sat in — the height left
     over once the copy had taken what it needed — and corrected for the copy's
     length with a measured constant per language: 551px in English, 618px in
     Arabic. Both constants went stale the moment the copy changed. The agency's
     Arabic landed on 10 September and runs longer, so in Arabic the cap stopped
     binding and the row took over again: measured at 390x745, the three
     chapters came back 127, 102 and 127 against a flat 194 in English, which is
     the exact per-chapter inequality the constants were introduced to remove.

     So the mark is sized from the inline axis instead, the way the desktop
     column already sizes it — the one axis that has nothing to do with how long
     the copy is. Nothing here needs retuning when copy changes, and the two
     languages agree by construction rather than by measurement. 68vw sets it on
     a tall phone; 28svh takes over on a short one, so the copy still wins the
     space it needs rather than being pushed off the bottom. 28 rather than 30
     because at 360x720 -- a common Android viewport -- 30svh left the longest
     Arabic chapter's link 9px under the fold. Measured equal in both languages,
     with nothing below the fold, at 390x745, 390x844, 393x852, 414x896, 430x932
     and 360x720. */
  .slide{grid-template-rows:auto minmax(0,1fr)}
  .slide-media{order:-1;width:min(68vw,var(--media-w),28svh);height:auto}
}

/* Below this height there is no arrangement that holds: the mark shrinks to a
   speck and the copy still runs off the bottom. The chapter drops the image and
   runs as copy instead. One threshold for both languages — they now set to the
   same height, so the point where the sum fails is the same for both.

   The row template has to come back with it. Hiding the mark takes it out of
   flow, so the copy falls into the first row — which is the mark's `auto` row
   above, and an auto row is free to grow past the viewport. Measured at 320x568
   in Arabic: the copy stood 531px tall in a 452px space and pushed its link 7px
   under the fold. One constrained row instead, which is what the copy had here
   before the mark was ever sized from the inline axis. */
@media (max-width:560px) and (max-height:719px){
  .slide-media{display:none}
  .slide{grid-template-rows:minmax(0,1fr)}
}
/* The mark answers the first flick. The prototype held it flat for the first
   30% of the arrival's range, which is a third of a screen on a phone and about
   450px on a 1440x900 desktop: the page moved and the mark did not. The phone
   was retuned to 6% in 0.11.0 and the desktop followed at the client's request,
   so the two now behave the same and the offsets live in one place. Only the
   hold changes; ovWord, ovShrink, ovBar and ovIcon are untouched. */
@keyframes ovLogo{0%,6%{transform:translateY(0) scale(1);opacity:var(--logo-veil)}78%,100%{transform:translateY(var(--logo-rise)) scale(var(--logo-scale));opacity:1}}
@keyframes ovWord{0%,78%{opacity:1}88%,100%{opacity:0}}
@keyframes ovTitle{to{opacity:0}}
@keyframes ovShrink{0%,86%{transform:scale(1)}100%{transform:scale(0.84)}}
/* The step back, retuned for a phone for the same reason ovLogo was. The
   prototype's 86%-100% window is 252px of scroll on a 1440x900 desktop and was
   94px at 390x745 -- the same 16% move in a third of the distance, on a frame
   narrow enough that scale(0.84) opens a 31px gutter down each side and lifts
   the image 59px clear of the top. Measured, not guessed: the rect went
   0,0,390,745 to 59,31,328,626, so what read as a step back on the comp read
   as the picture coming loose here. A longer window and a shallower end point
   keep the gesture and lose the seam -- 64%-100% is 375px of scroll for a 6%
   move, and 0.94 holds the gutter to 12px. */
@media (max-width:1023px){
  @keyframes ovShrink{0%,64%{transform:scale(1)}100%{transform:scale(0.94)}}
}
@keyframes ovBar{0%,86%{background-color:rgba(34,34,35,0);border-block-end-color:rgba(214,210,196,0)}100%{background-color:rgba(34,34,35,1);border-block-end-color:rgba(214,210,196,0.34)}}
@keyframes ovIcon{0%,88%{visibility:hidden}100%{visibility:visible}}
@supports (animation-timeline: view()){
  .logo-block,.logo-word,.ov-inner,.bar-home,.bar-home .bar-icon{animation-duration:auto;animation-timing-function:linear;animation-fill-mode:both;animation-timeline:--ov;animation-range:contain 0% contain 100%}
  .logo-block{animation-name:ovLogo}.logo-word{animation-name:ovWord}.ov-inner{animation-name:ovShrink}
  .ov-head{animation-name:ovTitle;animation-duration:auto;animation-timing-function:linear;animation-fill-mode:both;animation-timeline:scroll(root);animation-range:0 30svh}
  .bar-home{animation-name:ovBar}.bar-home .bar-icon{animation-name:ovIcon}
}

/* Overture entrance. Runs once per session off the .intro class, on wrapper
   elements only. The @supports (animation-timeline: view()) block above
   drives five elements on scroll — .logo-block, .logo-word, .ov-inner,
   .bar-home and .bar-home .bar-icon — and none of the five may be targeted
   here: the entrance would either fight one of them for the same property,
   or, worse, the animation shorthand would reset animation-timeline back to
   auto and silently detach it from --ov. .ov-arrive and .ov-rise wrap the
   scroll-driven .logo-block/.ov-inner pairing; .ov-word exists for the same
   reason, wrapping .logo-word so the entrance never touches it directly. */
.ov-arrive{display:flex;align-items:center;gap:var(--logo-gap)}
.ov-rise{position:absolute;inset:0}
.ov-word{display:flex;flex:none}
.ov-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 40%;opacity:0;
  transition-property:opacity;transition-duration:var(--dur-signature);transition-timing-function:var(--ease-out)}
.ov-video[data-ready="1"]{opacity:1}

@keyframes introRise{from{transform:scale(1.06)}to{transform:scale(1)}}
@keyframes introVeil{0%,18%{opacity:1}30%,100%{opacity:0}}
@keyframes introIcon{0%,38%{opacity:0;transform:translateY(18px)}100%{opacity:1;transform:none}}
@keyframes introWord{0%,56%{opacity:0;transform:translateY(14px)}100%{opacity:1;transform:none}}
/* introArrive carries no visible motion of its own (from/to both opacity:1)
   — .ov-arrive's children carry the visible work. It exists so .ov-arrive is
   the fifth member of tools/checks/entrance.js's introCount === 5 gate, and
   so the wrapper itself is anchored inside the same startTime /
   settleDurationMs span as its children rather than falling outside it. */
@keyframes introArrive{from{opacity:1}to{opacity:1}}

.intro .ov-rise{animation:introRise 1100ms var(--ease-unfold) both}
.intro .ov-scrim::before{animation:introVeil 1100ms var(--ease-unfold) both}
.intro .ov-arrive{animation:introArrive 1100ms var(--ease-unfold) both}
.intro .ov-arrive .logo-icon{animation:introIcon 1100ms var(--ease-unfold) both}
.intro .ov-arrive .ov-word{animation:introWord 1100ms var(--ease-unfold) both}
.intro .ov-title{animation:introWord 1100ms var(--ease-unfold) both}

@media (prefers-reduced-motion: reduce){
  .overture{height:100svh}
  .logo-block{position:absolute;animation:none!important;transform:none!important}
  .logo-word{animation:none!important}
  .ov-head{animation-name:none}
  .bar-home{animation:none!important;background:var(--black);border-block-end-color:var(--rule-accent)}
  .bar-home .bar-icon{animation:none!important;visibility:visible}
  .slide-wrap{height:auto;overflow:visible;clip-path:none}
  .slide{position:static;inset:auto;min-height:100svh}
}

.strip{display:flex;gap:var(--gutter);overflow-x:auto;scrollbar-width:none;scroll-snap-type:x proximity;padding-inline:var(--margin)}
.strip::-webkit-scrollbar{display:none}
.strip > *{scroll-snap-align:start}
.grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-8) var(--gutter)}
.grid4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--space-7) var(--gutter)}
@media (max-width:1023px){.grid3{grid-template-columns:repeat(2,minmax(0,1fr))}.grid4{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){.grid3,.grid4{grid-template-columns:minmax(0,1fr)}.grid3 .wide{grid-column:auto}}
.wide{grid-column:span 2}
.card .shot{position:relative;overflow:hidden;background:var(--media-ground)}
.card .shot .photo,.card .shot .swap{position:absolute;inset:0;background-size:cover;background-position:center;transition:transform var(--dur-hover) var(--ease-out),opacity var(--dur-hover) var(--ease-out)}
/* The swap fades in ON TOP of a photo that stays opaque. Fading the photo
   out at the same time drops combined coverage to 0.75 halfway through --
   measured, 11 September -- and the media ground reads as a flash in the
   middle of every hover. One layer animates, not two. */
.card .shot .swap{opacity:0}
@media (hover:hover){
  .card:hover .shot .photo{transform:scale(1.03)}
  .card:hover .shot .swap{opacity:1;transform:scale(1.03)}
}
.badge{position:absolute;inset-block-start:0;inset-inline-start:0;background:var(--black);color:var(--cream);padding:var(--space-2) var(--space-4);font:var(--type-eyebrow);letter-spacing:var(--track-eyebrow);text-transform:uppercase}

.ground-black{--media-ground:color-mix(in oklab,var(--black) 86%,var(--cream) 14%);--surface-wash:rgba(214,210,196,0.06);--surface:var(--black);--ink:var(--cream);--ink-muted:var(--ink-muted-black);--rule:var(--rule-black);--rule-strong:var(--rule-strong-black);--accent-ink:var(--terracotta-ink-black);--counter:var(--cream);--counter-ink:var(--black);--sec-fill:var(--terracotta-ink-cream);background:var(--surface);color:var(--ink)}
.ground-cream{--media-ground:color-mix(in oklab,var(--cream) 86%,var(--black) 14%);--surface-wash:rgba(34,34,35,0.05);--surface:var(--cream);--ink:var(--black);--ink-muted:var(--ink-muted-cream);--rule:var(--rule-cream);--rule-strong:var(--rule-strong-cream);--accent-ink:var(--terracotta-ink-cream);--counter:var(--terracotta-ink-cream);--counter-ink:var(--cream);--sec-fill:var(--black);background:var(--surface);color:var(--ink)}
.pad{padding:var(--section-block) var(--margin)}
.pagetop{padding:calc(var(--bar-h) + var(--space-9)) var(--margin) var(--space-7)}
.eyebrow{font:var(--type-eyebrow);letter-spacing:var(--track-eyebrow);text-transform:uppercase;color:var(--accent-ink)}
.h1{font:var(--type-display-2xl);letter-spacing:var(--track-display-xl);text-transform:uppercase;margin:0}
.h2{font:var(--type-display-lg);letter-spacing:var(--track-display);text-transform:uppercase;margin:0}
.h3{font:var(--type-display-md);letter-spacing:var(--track-display);text-transform:uppercase;margin:0}
.body{font:var(--type-body);text-wrap:pretty}
/* Links inside running text: the Visit booking line, the FAQs and Contact
   telephone, and any a kitchen story carries. The prototype never drew one,
   and these read as plain text and measured 16px tall. The underline marks
   them; the padding is the 44px target and the matching negative margin
   keeps the line box the height it was; inline-block because a transform
   does nothing to an inline box. */
.body a:not(.px){display:inline-block;padding-block:calc((var(--target-min) - 1lh) / 2);margin-block:calc((1lh - var(--target-min)) / 2);text-decoration-line:underline;text-decoration-thickness:var(--hairline);text-underline-offset:0.2em;transition-property:color,transform;transition-duration:var(--dur-micro),var(--dur-release);transition-timing-function:var(--ease-out),var(--ease-release)}
@media (hover:hover){.body a:not(.px):hover{color:var(--accent-ink)}}
.body a:not(.px):active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
.cap{font:var(--type-caption);color:var(--ink-muted);text-wrap:pretty}
.head-row{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--space-6);flex-wrap:wrap;margin-block-end:var(--space-7)}
.fact{display:flex;align-items:flex-start;gap:var(--space-4);border-block-start:var(--hairline) solid var(--rule);padding-block-start:var(--space-4)}
.side{border:var(--hairline) solid var(--rule-strong);padding:var(--space-6);display:flex;flex-direction:column;gap:var(--space-5);position:sticky;inset-block-start:calc(var(--bar-h) + var(--space-5))}
.two{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);gap:var(--space-9);align-items:start}
@media (max-width:1023px){.two{grid-template-columns:minmax(0,1fr);gap:var(--space-7)}.side{position:static}}
.rows > *{border-block-start:var(--hairline) solid var(--rule)}
.foot a:not(.px){transition:color var(--dur-micro) var(--ease-out),border-color var(--dur-micro) var(--ease-out),transform var(--dur-release) var(--ease-release)}
.foot a:not(.px):active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
.foot{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--space-7) var(--gutter)}
@media (max-width:1023px){.foot{grid-template-columns:repeat(2,minmax(0,1fr))}.foot > *:last-child{grid-column:span 2}}
@media (max-width:560px){.foot{grid-template-columns:minmax(0,1fr)}.foot > *:last-child{grid-column:auto}}

/* Story — one two-column composition that transforms between two content families. Everything
   visual is written per frame from a single phase value in the logic class, so the ground colour,
   both photographs and the copy travel as one scene rather than as four independent swaps. */
.story{position:relative;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);min-height:min(42svh,420px);isolation:isolate}
/* The ground pair, not two named colours: story.js interpolates --surface
   and --ink across a scene change and every token-driven child follows.
   The literal black/cream this replaces meant the button kept scene one's
   ink while the ground behind it moved to cream. */
.story-ground{position:relative;display:flex;flex-direction:column;justify-content:space-between;gap:var(--space-5);padding-block:var(--space-7);padding-inline:var(--margin) var(--space-7);background:var(--surface);color:var(--ink)}
.story-copy{display:flex;flex-direction:column;gap:var(--space-5);will-change:transform,opacity}
.story-eyebrow{font:var(--type-eyebrow);letter-spacing:var(--track-eyebrow);text-transform:uppercase;will-change:transform,opacity}
.story-head{font:300 clamp(22px,2.1vw,36px)/1.06 var(--font-display);letter-spacing:var(--track-display);text-transform:uppercase;margin:0;max-width:26ch;text-wrap:pretty}
.story-sub{font:var(--type-caption);opacity:.78;max-width:42ch;text-wrap:pretty;margin:0}
.story-media{position:relative;overflow:hidden;background:var(--media-ground)}
.story-layer{position:absolute;inset:0;overflow:hidden;will-change:transform,opacity}
.story-layer > div{position:absolute;inset:-3%;background-size:cover;background-position:center;will-change:transform}
.story-ring{position:absolute;inset-block-start:var(--space-5);inset-inline-start:var(--space-5);z-index:3;display:grid;place-items:center;width:var(--target-min);height:var(--target-min);background:var(--black)}
.story-arc{transition:none}
/* story.js already moves --ink smoothly across a scene change, so the
   label's own colour transition only adds lag on top of it -- the ground
   reaches cream while the label is still most of the way to it, and for
   about half a second the label is cream on cream. Duration only, so the
   longhand transition-property stays intact and the press model holds. */
.story-cta > span{transition-duration:0s}
.story-nav{position:absolute;inset-block-start:var(--space-5);inset-inline-end:var(--space-5);z-index:3;display:flex;background:var(--black)}
.story-tab{display:inline-flex;align-items:center;gap:var(--space-3);min-height:var(--target-min);padding-inline:var(--space-5);background:none;border:0;cursor:pointer;font:var(--type-ui);letter-spacing:var(--track-ui);text-transform:uppercase;white-space:nowrap;color:var(--ink-muted-black);transition:color var(--dur-micro) var(--ease-out),transform var(--dur-release) var(--ease-release)}
.story-tab + .story-tab{border-inline-start:var(--hairline) solid var(--rule-strong-black)}
.story-tab i{width:8px;height:8px;flex:none;background:var(--rule-strong-black);transition:background var(--dur-micro) var(--ease-out),transform var(--dur-pixel) var(--ease-in-out)}
.story-tab[data-on="1"]{color:var(--cream)}
.story-tab[data-on="1"] i{background:var(--terracotta-ink-black);transform:scale(1.35)}
.story-tab:active{transform:scale(var(--press-soft));transition-duration:var(--dur-press);transition-timing-function:var(--ease-press)}
@media (hover:hover){.story-tab:hover{color:var(--cream)}.story-tab:hover i{background:var(--terracotta-ink-black)}}
@media (max-width:1023px){.story{grid-template-columns:minmax(0,1fr);min-height:0}
  .story-media{order:-1;aspect-ratio:var(--ar-wide)}
  .story-ground{padding:var(--space-7) var(--margin);gap:var(--space-6)}
  .story-nav{inset-block-start:auto;inset-block-end:0;inset-inline:0;justify-content:stretch}
  .story-tab{flex:1 1 0;justify-content:center}}

/* Coming soon -- the holding page in parts/coming-soon.php. body wears .ground-black, so the pair
   is already set and nothing below picks a colour of its own.

   The photograph sits inside the mark's own silhouette, the same treatment .slide-media gives the
   story closer, rather than washing the whole screen: the hall's ceiling sign already reads
   MSHEIREB FOODHALL, and behind the wordmark it fought it. Sized off the short edge (svh), because
   the mark is square and the screen it has to fit is usually not. 100svh, not vh, so a phone's URL
   bar cannot push the stack off the screen. */
.soon{position:relative;min-height:100svh;display:grid;place-items:center;padding:var(--space-8) var(--margin)}
.soon-inner{display:grid;justify-items:center;gap:var(--space-6);text-align:center;width:min(560px,100%);animation:rise var(--dur-signature) var(--ease-out) both}
.soon-media{width:min(100%,var(--media-w),46svh);aspect-ratio:var(--mark-ar);overflow:hidden;background:var(--media-ground);clip-path:var(--mark)}
.soon-media img{width:100%;height:100%;object-fit:cover;object-position:50% 38%;display:block}
.soon-mark{width:min(400px,86%);height:auto;margin-block-start:var(--space-2)}
.soon-line{font:var(--type-display-md);letter-spacing:var(--track-display);text-transform:uppercase;color:var(--ink);margin:0}
.soon-social{justify-content:center;width:100%;margin-block-start:var(--space-2);padding-block-start:var(--space-6);border-block-start:var(--hairline) solid var(--rule)}

/* Reduced motion — LAST in the sheet on purpose. These resets have the same specificity as the
   press rules above, so source order is what defeats them. Anything added later must go BELOW. */
@media (prefers-reduced-motion:reduce){
.px,.fdfil button,.vtoggle,.card,.vmedia,.vname,.namerun,.namerun b,.namerun-go,.press-card,.cov,.menu-row,.story-tab,.bar-home-link,.menu-home-link,.role,.foot a:not(.px),.body a:not(.px),.visit-map-open,.vmedia .photo,.card .photo,.band-media .photo,.band-media .swap,.band,.efeat,.ov-video{transition:none}
.intro .ov-rise,.intro .ov-scrim::before,.intro .ov-arrive,.intro .ov-arrive .logo-icon,.intro .ov-arrive .ov-word,.intro .ov-title{animation:none}
.px:active,.fdfil button:active,.vtoggle:active,.card:active,.vmedia:active,.vname:active,.namerun-go:active b,.press-card:active,.cov:active,.menu-row:active,.bar-home-link:active,.menu-home-link:active,.role:active,.foot a:not(.px):active,.body a:not(.px):active,.visit-map-open:active,.vmedia:active .photo,.card:active .photo,.band:active,.efeat:active{transform:none}
.namerun > span{animation:none}
.soon-inner{animation:none}
.vbody,.vbody::after{transition:none}
}
