/* v4 site theme, loaded last on every page.
   One accent (v3 gold #efb52e, restored 10/9 at the user's request), quiet buttons,
   slow fades without bounce, lighter section headings. Hero h1 untouched. */
:root{--gold:#efb52e;--gold-deep:#efb52e;--ucs-entry-ease:cubic-bezier(.25,.6,.25,1);--ucs-control-ease:cubic-bezier(.25,.6,.25,1)}

/* Buttons: dark pill, gold hairline and text; filled only on hover.
   !important because page CSS such as .spf-page .button outranks a site-wide rule. */
html body :is(a.button,button.button){background:#0f1a22!important;color:var(--gold)!important;border:1px solid rgba(239,181,46,.75)!important;box-shadow:none;transition:background-color .4s ease,color .4s ease,border-color .4s ease}
html body :is(a.button,button.button) *{color:inherit}
html body :is(a.button,button.button):hover{background:var(--gold)!important;color:#111e28!important;border-color:var(--gold)!important}

/* Section headings: lighter serif. Hero h1 keeps its weight. */
html:not([lang=en]) body main :is(h2,h3):not(.eyebrow){font-weight:400!important}

/* Motion: slow fades, no overshoot, no lift on hover (cards: a slight scale since 10/20, below) */
.ucs-motion-ready [data-scroll-entry],.ucs-motion-ready [data-entry-kind="card"]{transition:opacity .9s ease,translate .9s var(--ucs-entry-ease)!important;transition-delay:var(--entry-delay,0ms)!important}
.ucs-motion-ready [data-scroll-entry]:not(.has-entered),.ucs-motion-ready [data-entry-kind="card"]:not(.has-entered){translate:0 10px;scale:none}
html body :is(a.button,button.button,.nav-enquiry,.round-arrow,.gallery-controls button,.partner-pause,.res-next__choice,.company-member__link,.sp-tech-card):is(:hover,:active,:focus-visible){transform:none!important;box-shadow:none!important}
html body :is(.service-scene:hover .scene-link i,.text-link:hover>span[aria-hidden],.expertise-row:hover .arrow){transform:none!important}
html body :is(.work-card:hover .work-card__image:not(.footprint__map),.service-scene:hover>img,.sp-tech-card:hover .card__image){transform:scale(1.01)!important;transition:transform 1.6s var(--ucs-entry-ease)!important}
/* Cards on hover (10/20, user): no gold hairline round the card any more; it grows very slightly.
   A faint gold shadow under it was tried the same day and taken off (the user did not like the glow).
   Covers the homepage service and process cards, 前沿科技's area cards, 資訊保安's service cards and
   家居保安's closing choices. :root raises the specificity above the
   entry-motion rule above, whose transition list would otherwise drop the scale. */
:root body :is(.svc-card,.process-quiet__card,.sp-tech-card,.it-card,.res-next__choice){
  transition:opacity .9s ease,translate .9s var(--ucs-entry-ease),scale .6s var(--ucs-entry-ease),border-color .6s ease!important;
  transition-delay:var(--entry-delay,0ms),var(--entry-delay,0ms),0ms,0ms!important}
:root body :is(.svc-card,.process-quiet__card,.sp-tech-card,.it-card,.res-next__choice):is(:hover,:focus-visible){
  scale:1.015}
:root body :is(.sp-tech-card,.res-next__choice):is(:hover,:focus-visible){border-color:rgba(210,220,229,.15)!important}
@media(prefers-reduced-motion:reduce){:root body :is(.svc-card,.process-quiet__card,.sp-tech-card,.it-card,.res-next__choice):is(:hover,:focus-visible){scale:none}}
/* 10/12: closing particles back on (user request) */

/* Contrast: inactive chapter numbers were #737d8a on #101d27 (4.1:1); now 5.8:1 */
html body .progress-chapters a .number{color:#8d98a4}

/* Phone legibility and touch targets (10/12).
   Text sits in <span data-zh|data-en> inside each styled element, so max(<floor>, 1em) on those
   spans is a true minimum: 1em is the size the element already had, nothing gets smaller. */
@media (max-width:650px){
  html body :is([data-zh],[data-en]){font-size:max(13px,1em)!important}
  html body :is(.work-credit,figcaption) :is([data-zh],[data-en]){font-size:max(11px,1em)!important}
  /* labels whose text is not wrapped in a language span */
  html body :is(.vpd-index,.vpd-step,.practice-option-number,.pjx-item__no,.pjx-filters sup,.bmodel__pin b,
    .res-chapters .number,.progress-chapters .number,.res-building-process__heading .number,
    figcaption,figcaption a,.work-credit,.work-credit a,.footer-bottom>span,.footer-bottom>a,.company-scene__foot>span,
    .drone-survey-deliverables li>span){font-size:12px!important}
  html body .lang-switch button{font-size:13px!important}

  /* touch targets: at least 44px tall without moving the visible design */
  html body :is(.lang-switch button,.text-link,.cinema-secondary,.bmodel__pin){position:relative}
  html body :is(.lang-switch button,.text-link,.cinema-secondary,.bmodel__pin)::before{content:"";position:absolute;left:-4px;right:-4px;top:50%;height:44px;translate:0 -50%}
  html body .brand{padding-block:9px}
  html body :is(.footer-links a,.footer-bottom a,.footer-contact a){display:flex;align-items:center;min-height:44px;margin-block:0}
  html body .pjx-filters button{min-height:40px}
  html body .pjx-views button{min-width:40px;min-height:40px}
  html body .contact-directions a{display:inline-flex;align-items:center;min-height:44px}
}

/* One continuous page (10/12). Sections used to sit on ~12 different dark tones with hard
   edges; now every block shares one ground, heroes fade into it, and cards share one finish. */
:root{--v4-ground:#111e28;--v4-card:#152431;--v4-line:rgba(246,245,239,.08)}
html body{background:var(--v4-ground)}
html body :is(main>section,main>div,main>nav,main>.spf-page>section,main>.spf-page>div,main>.pjx>section,main>.pjx>div,.site-footer){background-color:transparent!important}
html body .site-footer{border-top:1px solid var(--v4-line)}
/* the chapter bar stays readable when it sticks over content */
html body .res-chapters{background-color:rgba(17,30,40,.94)!important;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}
/* hero photographs dissolve into the ground instead of ending on an edge */
html body :is(.opening-cinema .hero-media,.res-hero .hero-media,.res-building-hero .hero__image,.spf-hero__media,.company-scene__image){
  -webkit-mask-image:linear-gradient(to bottom,#000 72%,transparent);mask-image:linear-gradient(to bottom,#000 72%,transparent)}
/* ...and so do the shading layers laid over them (10/13): their left-hand darkening used to
   stop on a hard line at the bottom of the hero */
html body :is(.opening-cinema,.res-hero,.res-building-hero,.spf-hero)::after,html body :is(.company-scene__shade,.hero-veil){
  -webkit-mask-image:linear-gradient(to bottom,#000 72%,transparent);mask-image:linear-gradient(to bottom,#000 72%,transparent)}
/* one card finish */
html body :is(.work-card,.service-scene,.spf-service,.sp-tech-card,.card){border-radius:12px;border-color:var(--v4-line)}
html body :is(.work-card--map,.spf-service){background-color:var(--v4-card)}
/* the large panels (engineering steps, drone spec, practice console) were grey or teal boxes on the navy ground */
html body :is(.engineering-panel,.drone-spec-card,.practice-console){background-color:var(--v4-card)!important;border-color:var(--v4-line)!important}
html body :is(.engineering-outcomes,.drone-spec-highlights,.practice-network){background-color:rgba(246,245,239,.03)!important;border-color:var(--v4-line)!important}
/* full-width section backdrops (quote textures, D-Fence eagle) fade in and out at both ends */
/* (pseudo-elements cannot sit inside :is(), so the shading layers get their own selectors) */
html body :is(.consultant-quote__background,.dfence-r2__background),html body :is(.consultant-quote,.dfence-r2)::before,html body :is(.consultant-quote,.dfence-r2)::after{
  -webkit-mask-image:linear-gradient(to bottom,transparent,#000 22%,#000 78%,transparent);mask-image:linear-gradient(to bottom,transparent,#000 22%,#000 78%,transparent)}

/* Film grain (10/13): a still, very fine noise over everything (tools/grain.py). It gives the
   flat navy and the photographs one surface, and breaks up banding in the dark fades. */
html body::after{content:"";position:fixed;inset:0;z-index:2147483000;pointer-events:none;background:url("img/grain.png") 0 0/192px 192px;opacity:.5}
/* on high-density screens one grain = one device pixel */
@media (min-resolution:2dppx){html body::after{background-size:96px 96px;opacity:.7}}
@media print{html body::after{display:none}}

/* Hairlines draw in from the left (10/13, lines.js). border-image paints the element's own
   top/bottom rule up to --draw; lines.js removes the classes when the animation ends. */
@property --draw{syntax:"<percentage>";inherits:false;initial-value:100%}
@keyframes v4-draw-rule{from{--draw:0%}to{--draw:100%}}
@keyframes v4-draw-dash{from{scale:0 1}to{scale:1 1}}
@media (prefers-reduced-motion:no-preference){
  html body .v4-draw{--draw:0%;border-image:linear-gradient(to right,var(--rule) var(--draw),transparent var(--draw)) 1}
  html body .v4-draw.is-drawn{animation:v4-draw-rule 1.6s cubic-bezier(.6,0,.2,1) both;animation-delay:calc(var(--d,0s) + var(--entry-delay,0ms) + .15s)}
  html body .v4-draw-dash::before{transform-origin:0 50%;scale:0 1}
  html body .v4-draw-dash.is-drawn::before{animation:v4-draw-dash 1.2s cubic-bezier(.25,.6,.25,1) .3s both}
}

/* 10/15, from the taste-skill review: headings break into even lines and paragraphs avoid a lone last
   word or character, instead of whatever falls at the measure */
html body :is(h1,h2,h3,h4){text-wrap:balance}
html body :is(p,li,figcaption,blockquote){text-wrap:pretty}

/* Inner-page heroes share one type scale (10/20, user: the sizes did not match). v3 had three:
   家居保安 / 甲級商廈 / 認識 UCS (eyebrow 13px, title 5.1vw, line 18px), 前沿科技 / 私人委託 / 項目經驗
   (11px, 4.6vw, 17px) and 資訊保安 (11px, 3.6vw). All now take the first. */
html body main :is(.res-hero,.res-building-hero,.spf-hero,.company-scene) .eyebrow{font-size:13px!important;letter-spacing:.14em!important}
html body main :is(.res-hero,.res-building-hero,.spf-hero,.company-scene) h1{font-size:clamp(52px,5.1vw,78px)!important;line-height:1.3!important;letter-spacing:-.035em!important}
html body main :is(.res-hero,.res-building-hero,.spf-hero,.company-scene) .lede{font-size:18px!important;line-height:1.85!important}
@media(max-width:650px){
  html body main :is(.res-hero,.res-building-hero,.spf-hero,.company-scene) h1{font-size:clamp(36px,8.8vw,52px)!important;line-height:1.36!important;letter-spacing:-.045em!important}
  html body main :is(.res-hero,.res-building-hero,.spf-hero,.company-scene) .lede{font-size:16px!important;line-height:1.8!important}
}

/* Display lines in the title face (10/20, user: "why is this not Song?"). The 10/06 rule keeps Sung for
   titles and quotations and Hei for everything else; these lines are display text, not running copy:
   the footer statement on every page (23px), the founder's lead, the company lead on 認識 UCS and the
   lead of each 資訊保安 service row, each set right under a Sung heading. */
html body :is(.footer-statement,.founder__lead,.story__lead,.it-row__lead),
html body :is(.footer-statement,.founder__lead,.story__lead,.it-row__lead) *{font-family:var(--serif)!important;font-weight:400!important}

/* Phones (10/21, user: 「手機版整體所有字體好像都很幼小」). Reading copy was mostly 14–15px and labels 13px, in
   the Hei at 400, which a phone screen draws thin. Below 650px: reading copy 16px, labels and links 14px, buttons
   15px, small numerals 12px, and the Chinese a step heavier at 450 (the Hei is variable, 300–500). General Sans is
   static, so 450 maps to its Regular here and the English keeps its weight. Headings are unchanged. */
@font-face{font-family:"UCS English";font-style:normal;font-weight:450;font-display:swap;src:url("../../v3/assets/fonts/brand/GeneralSans-Regular.woff2") format("woff2")}
@media(max-width:650px){
  html body{font-weight:450}
  html body main :is(.opening-cinema .lede,.service-scene__copy p,.svc-card__body p,.process-quiet p,.lm-item__lead,.it-row__body,
    .card__body p:not(.card__meta),.care-plan__desc,.care-plan__checks li,.res-output-map li,.spf-labels li,.story__points li,
    .sp-intake p,.spf-service__body p,.contact-steps p){font-size:16px!important;line-height:1.8!important}
  html body main :is(.eyebrow,.text-link,.scene-link,.sp-card-link,.svc-card__link,.pjx-item__loc,.fp-row__aside,.fp-row__kind,
    .fp-row__place,.fp-chip,.lm-item__kicker,.story__service,.spf-flow-key,.sp-owner,.card__meta,.drone-spec-value,
    .ct-chip>span,.ct-field label,.opening-credentials p){font-size:14px!important}
  html body main :is(.res-hero,.res-building-hero,.spf-hero,.company-scene,.opening-cinema) .eyebrow{font-size:14px!important}
  html body :is(main,.site-footer) a.button{font-size:15px!important}
  html body main :is(.fp-row__no,.spf-service__mark,.drone-step-visual){font-size:12px!important}
  /* iOS 26 Safari draws the page under the status bar; once the header is solid it carries its colour up over it */
  html body .site-header.is-scrolled{background:#171c25;-webkit-backdrop-filter:none;backdrop-filter:none}
  html body .site-header::before{content:"";position:absolute;left:0;right:0;bottom:100%;height:160px;background:inherit;pointer-events:none}
}
