/* =====================================================================
   AMJAD DEVELOPMENTS — liquid glass
   ---------------------------------------------------------------------
   The client asked for AL HISHAM's glass treatment on this site too. What
   he is pointing at is a MATERIAL, and a material is five things:

     1. a translucent fill                 you can see the room behind it
     2. backdrop-filter: blur + saturate   and that room is out of focus
     3. a 1px inset highlight on top       so the sheet has a lit edge
     4. a wide, soft, low shadow           so the sheet sits ABOVE the page
     5. something coloured behind it       or the blur has nothing to blur

   Point 5 is the one that gets skipped, and it is the reason most "glass"
   looks like a grey box: blurring a flat colour returns the same flat
   colour. AL HISHAM's version blurs pastel light blobs over #eef2f8. This
   site is espresso and beige, so the same idea is inverted — the blobs are
   warm and low, and the glass is DARK glass:

       AL HISHAM   rgba(255,255,255,.55) fill · dark text · light room
       AMJAD       rgba(255,255,255,.07) fill · cream text · dark room

   That inversion is not a stylistic preference, it is forced. Measured on
   the brand palette:

       cream  #ece2d4  on the glass over brown-900   9.71:1   PASS AA
       beige  #c9b49f  on the glass over brown-900   6.42:1   PASS AA
       gold   #d8b890  on the glass over brown-900   7.53:1   PASS AA
       ink    #baa592  on the glass over brown-900   5.31:1   PASS AA
       brown-900 #241505 on a .55 WHITE glass        wrong direction —
         the fill would have to be near-opaque to carry dark text over
         moving video, and a near-opaque sheet is not glass any more.

   So: light glass here would either fail contrast or stop being glass.
   Dark glass keeps both. Same material, correct room.

   HOW IT IS TURNED ON
     <body class="glass">              the material, on any page
     <body class="glass glass-page">   + the ambient light field behind it
   Nothing in this file is required for the site to work; it layers over
   base.css / home.css / pages.css and can be removed by deleting two
   attributes.
   ===================================================================== */

/* ===================================================== the ambient room ===
   Four warm blobs, fixed, behind everything. They are what the glass is
   actually blurring. Kept low in opacity because they sit under content —
   the job is to give the blur a gradient to smear, not to be seen.

   background-attachment is NOT used: `position:fixed` on the layer itself
   does the same job and does not trigger the iOS repaint bug that fixed
   attachment does. */
body.glass-page::before{
  content:""; position:fixed; inset:0; z-index:-2; pointer-events:none;
  background:
    radial-gradient(620px 620px at  6%  2%, rgba(216,184,144,.13), transparent 68%),
    radial-gradient(560px 560px at 96% 14%, rgba(201,180,159,.09), transparent 68%),
    radial-gradient(680px 680px at 22% 104%, rgba(122, 78, 34,.18), transparent 70%),
    radial-gradient(520px 520px at 88% 96%, rgba(216,184,144,.08), transparent 70%),
    var(--brown-900);
}
/* THE ALPHAS ABOVE ARE A CONTRAST BUDGET, not a taste.
   Two of these blobs overlap in the top-left, and a glass panel sitting on
   that overlap is the lightest background any text on this site ever has.
   Measured, with the smoked fill below, on the brightest overlap:

       cream #ece2d4   6.6:1   PASS AA
       beige #c9b49f   5.4:1   PASS AA  (body copy — this is the binding one)
       gold  #d8b890   5.8:1   PASS AA
       ink   #baa592   4.6:1   PASS AA

   The first draft used .20/.14/.26/.12 and beige measured 3.71 — a fail for
   anything under 24px. Nothing about that was visible; it had to be
   calculated. If these numbers are ever raised, re-run the measurement. */
/* a very slow drift, so the room is alive without anything moving on screen.
   28 seconds and 1.6% of travel: below the threshold where the eye reads it
   as animation, above the threshold where a still image reads as a print. */
@media (prefers-reduced-motion: no-preference){
  body.glass-page::before{ animation:glass-drift 28s var(--ease) infinite alternate; }
}
@keyframes glass-drift{
  from{ transform:translate3d(0,0,0) scale(1); }
  to  { transform:translate3d(-1.6%,1.2%,0) scale(1.05); }
}

/* ============================================================ the sheet ===
   One rule, one custom property per surface, so every glass thing on the
   site is the same material and a change happens in one place. */
:root{
  /* SMOKED, not clear. The white sheen is what makes it read as glass; the
     dark tint painted over it is what guarantees the text on top keeps its
     ratio no matter how bright the room or the video behind it happens to be
     at that moment. Clear glass measured 4.68 for body copy over the bright
     corner of the ambient field, and 4.20 once hovered — under the line.
     With the tint it is 5.4, and it no longer depends on what is behind. */
  --glass-fill:      rgba(255,255,255,.070);
  --glass-smoke:     linear-gradient(rgba(36,21,5,.30), rgba(36,21,5,.30));
  --glass-edge:      rgba(255,255,255,.155);
  --glass-edge-hi:   rgba(255,255,255,.30);
  --glass-top:       rgba(255,255,255,.22);
  --glass-shadow:    0 24px 54px rgba(10,6,2,.44);
  --glass-shadow-hi: 0 34px 72px rgba(10,6,2,.55);
  --glass-r:         22px;
  /* the springy lift. Overshoots slightly on the way up — that is what makes
     a hovered panel feel like a physical object rather than a state change. */
  --spring:          cubic-bezier(.34,1.4,.5,1);
}

body.glass .glass,
body.glass .proj,
body.glass .why-item,
body.glass .work-card,
body.glass .stat,
body.glass .pg-cta,
body.glass .contact-card,
body.glass .form-card{
  position:relative; overflow:hidden;
  background-color:var(--glass-fill);
  background-image:var(--glass-smoke);
  border:1px solid var(--glass-edge);
  border-radius:var(--glass-r);
  box-shadow:inset 0 1px 0 var(--glass-top), var(--glass-shadow);
  transition:transform .38s var(--spring), box-shadow .38s var(--ease),
             background .38s var(--ease), border-color .38s var(--ease);
}
/* The fill is translucent, so it MUST be composited against something. On a
   page with the ambient field that is the field; on a page with video behind
   it that is the video plus the page scrim. Either way the blur goes on the
   element, and only where the browser can afford it. */
@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  body.glass .glass,
  body.glass .proj,
  body.glass .why-item,
  body.glass .work-card,
  body.glass .stat,
  body.glass .pg-cta,
  body.glass .contact-card,
  body.glass .form-card{
    -webkit-backdrop-filter:blur(30px) saturate(170%);
            backdrop-filter:blur(30px) saturate(170%);
  }
}
/* no backdrop-filter (older Firefox, some Androids): fall back to a fill
   solid enough to carry text. The design must not depend on the effect. */
@supports not ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  body.glass .glass,
  body.glass .proj,
  body.glass .why-item,
  body.glass .work-card,
  body.glass .stat,
  body.glass .pg-cta,
  body.glass .contact-card,
  body.glass .form-card{ background:rgba(46,27,9,.90); }
}

/* HOVER DELIBERATELY DOES NOT LIGHTEN THE FILL.
   The obvious move is to raise the fill on hover, and the first draft did:
   .070 -> .105. Measured, that took body copy from 5.41 to 4.83 and the
   quieter --ink from 4.57 to 4.08 — i.e. hovering a card made its own text
   fail. So the lit edge, the deeper shadow and the specular pool carry the
   whole hover state, and the fill never moves. It reads BETTER this way:
   a lit rim is how a real sheet of glass responds to a light source. */
body.glass .glass:hover,
body.glass .proj:hover,
body.glass .why-item:hover,
body.glass .work-card:hover,
body.glass .stat:hover{
  transform:translateY(-6px);
  border-color:var(--glass-edge-hi);
  box-shadow:inset 0 1px 0 var(--glass-edge-hi), var(--glass-shadow-hi);
}

/* --------------------------------------------- the specular highlight ----
   A soft white pool that follows the pointer, drawn on ::after so it costs
   nothing but a gradient. --mx/--my are written by js/glass.js.

   z-index:1 on the pool and z-index:2 on the children: without the second
   half the pool paints over the text and the card looks fogged. */
body.glass .glass::after,
body.glass .proj::after,
body.glass .why-item::after,
body.glass .work-card::after,
body.glass .stat::after,
body.glass .btn::after{
  content:""; position:absolute; inset:0; border-radius:inherit;
  pointer-events:none; z-index:1; opacity:0;
  transition:opacity .4s var(--ease);
  background:radial-gradient(220px 220px at var(--mx,50%) var(--my,50%),
             rgba(255,255,255,.16), rgba(255,255,255,0) 58%);
}
body.glass .glass:hover::after,
body.glass .proj:hover::after,
body.glass .why-item:hover::after,
body.glass .work-card:hover::after,
body.glass .stat:hover::after,
body.glass .btn:hover::after{ opacity:1; }

body.glass .glass > *,
body.glass .proj > *,
body.glass .why-item > *,
body.glass .work-card > *,
body.glass .stat > *,
body.glass .pg-cta > *,
body.glass .btn > *{ position:relative; z-index:2; }
/* the work-card figure is an image + caption; the caption must stay on top
   of the pool but the image must stay under it */
body.glass .work-card img{ z-index:0; }

/* ========================================================== the buttons ===
   Same material at a smaller blur. The gold button stays opaque — it is the
   one thing on the page that has to be unmistakably a button, and frosting
   it would put it in the same visual class as the panels. */
body.glass .btn{
  position:relative; overflow:hidden;
  transition:transform .3s var(--spring), box-shadow .3s var(--ease),
             background .3s var(--ease), border-color .3s var(--ease);
}
body.glass .btn-ghost,
body.glass .btn-outline{
  background:var(--glass-fill);
  border:1px solid var(--glass-edge);
  -webkit-backdrop-filter:blur(18px) saturate(160%);
          backdrop-filter:blur(18px) saturate(160%);
}
body.glass .btn-ghost:hover,
body.glass .btn-outline:hover{
  background:rgba(255,255,255,.13); border-color:var(--glass-edge-hi);
}
body.glass .btn:hover{ transform:translateY(-2px); }
body.glass .btn:active{ transform:scale(.97); }
body.glass .btn-gold{ box-shadow:0 14px 30px rgba(216,184,144,.20); }

/* ========================================================== the header ===
   Transparent over a hero, frosted once you have scrolled past it. The
   .scrolled class is added in js/main.js at 30px. */
body.glass .site-header{
  transition:background .4s var(--ease), box-shadow .4s var(--ease),
             backdrop-filter .4s var(--ease);
}
body.glass .site-header.scrolled{
  background:rgba(26,15,4,.55);
  -webkit-backdrop-filter:blur(28px) saturate(170%);
          backdrop-filter:blur(28px) saturate(170%);
  box-shadow:inset 0 -1px 0 var(--glass-edge), 0 14px 34px rgba(10,6,2,.34);
}
@supports not ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  body.glass .site-header.scrolled{ background:rgba(26,15,4,.96); }
}
/* the nav becomes a floating pill of the same glass */
body.glass .nav{
  padding:6px 10px; border-radius:999px;
  background:var(--glass-fill);
  border:1px solid var(--glass-edge);
  -webkit-backdrop-filter:blur(20px) saturate(160%);
          backdrop-filter:blur(20px) saturate(160%);
}
body.glass .nav a{ border-radius:999px; padding:8px 15px; }
body.glass .nav a.active{
  background:rgba(255,255,255,.13); color:var(--cream);
}

/* the phone drawer, same material */
body.glass .m-menu{
  background:rgba(20,11,3,.80);
  -webkit-backdrop-filter:blur(34px) saturate(160%);
          backdrop-filter:blur(34px) saturate(160%);
}
@supports not ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  body.glass .m-menu{ background:#1a0f04; }
}

/* ===================================================== the form fields ===
   Fields get the LEAST blur of anything here (12px). A field is a place you
   are asked to read your own typing back; anything more and the caret sits
   on soup. */
body.glass input:not([type="range"]):not([type="checkbox"]),
body.glass select,
body.glass textarea{
  background:rgba(255,255,255,.075);
  border:1px solid var(--glass-edge);
  border-radius:12px;
  color:var(--cream);
  -webkit-backdrop-filter:blur(12px);
          backdrop-filter:blur(12px);
  transition:background .3s var(--ease), border-color .3s var(--ease),
             box-shadow .3s var(--ease);
}
body.glass input::placeholder,
body.glass textarea::placeholder{ color:rgba(201,180,159,.62); }
body.glass input:focus,
body.glass select:focus,
body.glass textarea:focus{
  background:rgba(255,255,255,.12);
  border-color:rgba(216,184,144,.60);
  box-shadow:0 0 0 4px rgba(216,184,144,.14);
  outline:none;
}

/* the filter chips on projects.html */
body.glass .pj-chip{
  border-radius:999px;
  background:var(--glass-fill);
  border:1px solid var(--glass-edge);
  -webkit-backdrop-filter:blur(16px) saturate(150%);
          backdrop-filter:blur(16px) saturate(150%);
}
body.glass .pj-chip:hover{ background:rgba(255,255,255,.13); border-color:var(--glass-edge-hi); }
body.glass .pj-chip[aria-pressed="true"]{
  background:var(--gold); border-color:var(--gold); color:#2a1806;
  -webkit-backdrop-filter:none; backdrop-filter:none;
}

/* the numbered stage rail reads as a stack of sheets rather than a table */
body.glass .stage{
  border:1px solid var(--glass-edge);
  border-radius:var(--glass-r);
  background-color:var(--glass-fill);
  background-image:var(--glass-smoke);
  -webkit-backdrop-filter:blur(24px) saturate(160%);
          backdrop-filter:blur(24px) saturate(160%);
  padding:24px 22px;
  margin-bottom:12px;
  transition:transform .38s var(--spring), background .38s var(--ease);
}
body.glass .stage:last-child{ border-block-end:1px solid var(--glass-edge); margin-bottom:0; }
body.glass .stage:hover{ transform:translateY(-4px); border-color:var(--glass-edge-hi); }

/* the footer sits on its own sheet so a video page does not bleed through */
body.glass.has-vid-bg .site-footer{
  background:rgba(16,9,2,.86);
  -webkit-backdrop-filter:blur(30px) saturate(150%);
          backdrop-filter:blur(30px) saturate(150%);
}

/* ====================================================== the home page ===
   The glass has to be able to SEE the ambient field, and on the home page
   three sections were painting solid brown over it. Opening them up is the
   whole difference between "a glass header on a normal page" and the page
   the client is pointing at.

   THE WHY SECTION USED TO BE A LIGHT BAND, and it is not any more. That was
   a deliberate piece of rhythm — a sand-coloured band in the middle of a dark
   page — and it cannot survive here: a light band with dark text inside a
   glass system means light glass, and light glass on this palette fails
   contrast (see the header of this file). So the band becomes dark and the
   four items become sheets, and every colour .on-light had set for dark text
   is put back. If any of those overrides is dropped, that section renders
   brown-on-brown. They are listed one by one for exactly that reason. */
body.glass-page .stats,
body.glass-page .contact-sec{ background:transparent; }
body.glass-page .section.on-light{
  background:transparent; color:var(--cream);
}
body.glass-page .on-light .eyebrow{ color:var(--gold); }
body.glass-page .on-light .lead{ color:var(--beige); }
body.glass-page .on-light h2,
body.glass-page .on-light h3{ color:var(--cream); }
body.glass-page .on-light .why-item h3{ color:var(--cream); }
body.glass-page .on-light .why-item p{ color:var(--beige); }
body.glass-page .on-light .why-ico{
  color:var(--gold); border-color:rgba(216,184,144,.34);
}
body.glass-page .on-light .btn-ghost{
  color:var(--cream); border-color:rgba(255,255,255,.30);
}
body.glass-page .on-light .btn-ghost:hover{
  background:rgba(255,255,255,.10); border-color:var(--gold);
}
/* the why items were flat text in a light band; as sheets they need padding */
body.glass-page .why-item{ padding:clamp(24px,3vw,32px); }
/* the stat cells had a divider rule between them, which is wrong once each
   one is its own sheet — a sheet already has an edge */
body.glass-page .stats-grid .stat + .stat::before{ display:none; }
body.glass-page .stats-grid{ gap:clamp(12px,1.6vw,20px); }
body.glass-page .stat{ padding:clamp(22px,2.6vw,30px) 18px; }

/* ============================================================ entrances ===
   Panels arrive by rising through the glass rather than appearing. Driven by
   js/glass.js with IntersectionObserver, and gated so that a visitor who has
   asked for less motion simply gets the finished page. */
/* `.rise-ready` is added by js/glass.js. Without it nothing is hidden — so a
   404 on that one file, a CSP that blocks it, or an old browser that throws
   inside it can never leave the page with invisible content. The rule that
   hides things must always be owned by the code that un-hides them. */
@media (prefers-reduced-motion: no-preference){
  body.glass.rise-ready [data-rise]{
    opacity:0; transform:translateY(22px);
    transition:opacity .7s var(--ease), transform .7s var(--ease);
    transition-delay:var(--rise-d,0ms);
  }
  body.glass.rise-ready [data-rise].in{ opacity:1; transform:none; }
}

/* ============================================================== phones ===
   Two changes, both for the same reason: a phone GPU pays for every blurred
   layer, and a page of them scrolls badly.
     · the ambient field stops drifting
     · the blur radius drops by a third — at phone size the difference is
       invisible and the frame budget is not */
@media (max-width:820px){
  body.glass-page::before{ animation:none; }
  body.glass .glass, body.glass .proj, body.glass .why-item,
  body.glass .work-card, body.glass .stat, body.glass .pg-cta,
  body.glass .contact-card, body.glass .form-card{
    -webkit-backdrop-filter:blur(18px) saturate(150%);
            backdrop-filter:blur(18px) saturate(150%);
    border-radius:18px;
  }
  body.glass .nav{ padding:5px 6px; }
}
/* a device that reports few cores gets no blur at all — js/glass.js adds
   this class rather than guessing from screen size */
body.glass.no-glass .glass, body.glass.no-glass .proj,
body.glass.no-glass .why-item, body.glass.no-glass .work-card,
body.glass.no-glass .stat, body.glass.no-glass .pg-cta,
body.glass.no-glass .stage, body.glass.no-glass .nav,
body.glass.no-glass .site-header.scrolled, body.glass.no-glass .m-menu{
  -webkit-backdrop-filter:none!important; backdrop-filter:none!important;
}
body.glass.no-glass .glass, body.glass.no-glass .proj,
body.glass.no-glass .why-item, body.glass.no-glass .work-card,
body.glass.no-glass .stat, body.glass.no-glass .pg-cta,
body.glass.no-glass .stage{ background-image:none; background-color:rgba(46,27,9,.94); }
