/* ==========================================================================
   GALAD Business Solutions Ltd
   Core stylesheet
   --------------------------------------------------------------------------
   BRAND COLOUR: the single source of truth for GALAD red is --galad below.
   Sample the exact hex from the supplied logo file and change that one line;
   every button, rule, icon and gradient on the site follows it.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Brand */
  --galad:        #E61736;   /* primary red, sampled from the supplied logo */
  --galad-deep:   #BB1C28;   /* dark red, gradients and pressed states */
  --galad-ink:    #B01D2E;   /* red for small text on white (AA contrast) */
  --galad-wash:   #FDEFF1;   /* barely-there red tint for panels */

  /* Neutrals */
  --ink:          #131215;   /* near-black, sampled from the logo wordmark */
  --slate:        #16181D;   /* raised surface on dark */
  --graphite:     #2A2D34;   /* borders on dark */
  --paper:        #FFFFFF;
  --mist:         #F4F5F7;   /* light grey supporting background */
  --line:         #E3E5E9;   /* hairline on light */
  --body:         #4A4F58;   /* body text on light */
  --muted:        #6A6F78;   /* secondary text on light, AA on white and on mist */
  --muted-dark:   #9BA1AB;   /* secondary text on dark */
  --silver:       #C9CDD4;   /* soft silver detailing, used sparingly */

  /* Type */
  --display: "Instrument Serif", Georgia, "Times New Roman", serif;
  --sans: "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Rhythm */
  --wrap: 1180px;
  --gut: 24px;
  --sec: clamp(72px, 8vw, 118px);
  --hdr-h: 76px;          /* header height, and therefore the mobile panel offset */
  --radius: 4px;

  /* Depth */
  --shadow-sm: 0 1px 2px rgba(14, 15, 18, .05);
  --shadow-md: 0 10px 30px -18px rgba(14, 15, 18, .35);
  --shadow-lg: 0 30px 70px -40px rgba(14, 15, 18, .45);

  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%; scroll-behavior: smooth;
  scrollbar-gutter: stable;   /* keeps the page from shifting when the intro releases the scroll lock */
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--body);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { max-width: 100%; display: block; }
a { color: inherit; }

h1, h2, h3, h4 {
  color: var(--ink);
  margin: 0 0 .5em;
  font-weight: 400;
  letter-spacing: -.015em;
}

h1, h2 { font-family: var(--display); line-height: 1.06; }
h1 { font-size: clamp(40px, 5.6vw, 68px); }
h2 { font-size: clamp(31px, 3.7vw, 46px); }

h3, h4 { font-family: var(--sans); font-weight: 600; line-height: 1.3; letter-spacing: -.01em; }
h3 { font-size: clamp(19px, 1.5vw, 21px); }
h4 { font-size: 16px; }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

::selection { background: var(--galad); color: #fff; }

/* Focus: visible, brand-coloured, never removed */
:focus-visible {
  outline: 2px solid var(--galad);
  outline-offset: 3px;
  border-radius: 2px;
}
.on-ink :focus-visible { outline-color: #fff; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip {
  position: absolute; left: 16px; top: -60px; z-index: 200;
  background: var(--ink); color: #fff; padding: 12px 18px;
  font-size: 14px; font-weight: 600; text-decoration: none;
  border-radius: var(--radius); transition: top .2s var(--ease);
}
.skip:focus { top: 16px; }

/* --------------------------------------------------------------------------
   3. Layout
   -------------------------------------------------------------------------- */
.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gut); }
.wrap-tight { max-width: 880px; }

section { position: relative; }
.band { padding: var(--sec) 0; }
.band-sm { padding: clamp(52px, 5.5vw, 76px) 0; }

.s-paper { background: var(--paper); }
.s-mist  { background: var(--mist); }
.s-ink   { background: var(--ink); color: var(--muted-dark); }
.s-ink h1, .s-ink h2, .s-ink h3, .s-ink h4 { color: #fff; }
.s-mist + .s-mist { padding-top: 0; }
.s-paper + .band-sm.s-paper { padding-top: 0; }

.cols { display: grid; gap: clamp(28px, 4vw, 56px); }
@media (min-width: 900px) {
  .cols-2 { grid-template-columns: 1fr 1fr; }
  .cols-2-7 { grid-template-columns: 1.05fr .95fr; align-items: start; }
  .cols-side { grid-template-columns: 320px 1fr; }
}

.grid { display: grid; gap: 20px; grid-template-columns: 1fr; }
@media (min-width: 640px) { .grid-2, .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 980px) {
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
  .grid-4 { grid-template-columns: repeat(4, 1fr); }
}

/* --------------------------------------------------------------------------
   4. Section furniture
   The eyebrow rule is the recurring structural device: a short red hairline,
   then a mono label. It marks the start of every section, the way a ruled
   line marks the start of an entry in a ledger.
   -------------------------------------------------------------------------- */
.eyebrow {
  display: flex; align-items: center; gap: 12px;
  font-family: var(--mono); font-size: 11.5px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--galad-ink); margin: 0 0 20px;
}
.eyebrow::before { content: ""; width: 26px; height: 2px; background: var(--galad); flex: none; }
.s-ink .eyebrow { color: #F3939C; }

.lead { font-size: clamp(17px, 1.4vw, 19px); color: var(--body); max-width: 62ch; }
.s-ink .lead { color: var(--muted-dark); }
.head { max-width: 760px; margin-bottom: clamp(36px, 4vw, 54px); }
.head h2 { margin-bottom: .35em; }

.rule { height: 1px; background: var(--line); border: 0; margin: 0; }
.s-ink .rule { background: var(--graphite); }

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  font-family: var(--sans); font-size: 15px; font-weight: 600; line-height: 1;
  padding: 15px 26px; border-radius: var(--radius); border: 1px solid transparent;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background .22s var(--ease), color .22s var(--ease),
              border-color .22s var(--ease), transform .22s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn .arw { transition: transform .22s var(--ease); }
.btn:hover .arw { transform: translateX(3px); }

.btn-red { background: var(--galad); color: #fff; }
.btn-red:hover { background: var(--galad-deep); }

.btn-ink { background: var(--ink); color: #fff; }
.btn-ink:hover { background: var(--galad); }

.btn-line { border-color: var(--line); color: var(--ink); background: transparent; }
.btn-line:hover { border-color: var(--ink); background: var(--ink); color: #fff; }

.btn-ghost { border-color: rgba(255,255,255,.28); color: #fff; background: transparent; }
.btn-ghost:hover { border-color: #fff; background: #fff; color: var(--ink); }

.btn-sm { padding: 11px 18px; font-size: 14px; }
.btn-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }

/* On the narrowest phones a long label plus its padding can exceed the column,
   so buttons go full width and are allowed to wrap rather than push the page
   sideways. */
@media (max-width: 430px) {
  .btn { white-space: normal; padding: 14px 18px; }
  .btn-row .btn, .cal-actions .btn { width: 100%; }
}

.txtlink {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--galad-ink); font-weight: 600; font-size: 15px; text-decoration: none;
  border-bottom: 1px solid rgba(230, 23, 54, .3); padding-bottom: 2px;
  transition: border-color .2s var(--ease), gap .2s var(--ease);
}
.txtlink:hover { border-color: var(--galad); gap: 12px; }
.s-ink .txtlink { color: #F3939C; border-color: rgba(243,147,156,.35); }

/* --------------------------------------------------------------------------
   6. Header
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 80;
  background: rgba(255, 255, 255, .92);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
  transition: box-shadow .25s var(--ease);
}
.site-header.stuck { box-shadow: var(--shadow-md); }

.hdr { display: flex; align-items: center; gap: 20px; height: var(--hdr-h); }

.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; flex: none; }
.brand .markwrap { display: block; flex: none; line-height: 0; }
.brand .mark { height: 44px; width: auto; flex: none; }
.brand .wordmark { display: flex; flex-direction: column; line-height: 1; }
.brand .wordmark b {
  font-family: var(--display); font-size: 25px; font-weight: 400;
  color: var(--ink); letter-spacing: .01em;
}
.brand .wordmark span {
  font-family: var(--mono); font-size: 9px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--muted); margin-top: 4px;
}

.nav { margin-left: auto; display: none; align-items: center; gap: 2px; }
@media (min-width: 1060px) { .nav { display: flex; } }

.nav a.navlink, .nav button.navlink {
  font-family: var(--sans); font-size: 14.5px; font-weight: 500; color: var(--ink);
  background: none; border: 0; padding: 10px 13px; border-radius: var(--radius);
  text-decoration: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
  transition: color .2s var(--ease);
}
.nav .navlink:hover { color: var(--galad-ink); }
.nav .navlink[aria-current="page"] { color: var(--galad-ink); }
.nav .navlink { position: relative; }
.nav .navlink[aria-current="page"]::after {
  content: ""; position: absolute; left: 13px; bottom: 3px; width: 16px; height: 2px; background: var(--galad);
}

.has-drop { position: relative; }
.drop {
  position: absolute; top: calc(100% + 10px); left: -8px; min-width: 292px;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 8px; opacity: 0; visibility: hidden;
  transform: translateY(-6px); transition: opacity .18s var(--ease), transform .18s var(--ease), visibility .18s;
}
.has-drop:hover .drop, .has-drop:focus-within .drop, .drop.open { opacity: 1; visibility: visible; transform: none; }
.drop a {
  display: block; padding: 11px 13px; border-radius: var(--radius); text-decoration: none;
  font-size: 14.5px; font-weight: 500; color: var(--ink); transition: background .16s var(--ease);
}
.drop a small { display: block; font-weight: 400; font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.drop a:hover { background: var(--mist); }
.drop a:hover small { color: var(--body); }

.hdr-cta { display: none; margin-left: 14px; }
@media (min-width: 1060px) { .hdr-cta { display: inline-flex; } }

.burger {
  margin-left: auto; width: 46px; height: 46px; display: inline-flex;
  align-items: center; justify-content: center; background: none;
  border: 1px solid var(--line); border-radius: var(--radius); cursor: pointer;
}
@media (min-width: 1060px) { .burger { display: none; } }
/* Suppresses the 300ms double-tap-to-zoom gesture on the menu controls only.
   Pinch zoom is untouched, and no viewport tag restricts scaling. */
.burger, .mobile a, .mobile button {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.burger span { display: block; width: 18px; height: 1.5px; background: var(--ink); position: relative; transition: background .2s; }
.burger span::before, .burger span::after {
  content: ""; position: absolute; left: 0; width: 18px; height: 1.5px; background: var(--ink);
  transition: transform .25s var(--ease), top .2s var(--ease);
}
.burger span::before { top: -6px; }
.burger span::after { top: 6px; }
body.menu-open .burger span { background: transparent; }
body.menu-open .burger span::before { top: 0; transform: rotate(45deg); }
body.menu-open .burger span::after { top: 0; transform: rotate(-45deg); }

/* Mobile panel */
.mobile {
  position: fixed;
  top: var(--hdr-h);
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(100vh - var(--hdr-h));
  height: calc(100dvh - var(--hdr-h));
  z-index: 79;
  background: #fff;
  border-top: 1px solid var(--line);

  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;

  padding: 8px 0 max(40px, env(safe-area-inset-bottom));
  transform: translateY(-8px);
  opacity: 0;
  visibility: hidden;

  transition:
    opacity .22s var(--ease),
    transform .22s var(--ease),
    visibility .22s;
}
body.menu-open .mobile { opacity: 1; visibility: visible; transform: none; }

/* The background is held by position:fixed on body, applied in script, which
   is also what preserves the scroll offset. Nothing is written to html, so
   html cannot be left locked. The rule below stops the fixed body from
   growing its own scrollbar. */
body.menu-open { overflow: hidden; }

/* A fixed body has no scrolling ancestor, so the sticky header falls back to
   its static position, which is lockedScrollY pixels above the viewport, and
   disappears off the top. Pinning it while the menu is open is what keeps the
   header visually in place. Below the burger breakpoint only, since
   body.menu-open cannot occur once the burger is hidden. */
body.menu-open .site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}

.mobile .wrap > a, .mobile .acc-btn {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  padding: 17px 2px; font-size: 17px; font-weight: 500; color: var(--ink);
  text-decoration: none; border-bottom: 1px solid var(--line);
  background: none; border-left: 0; border-right: 0; border-top: 0; cursor: pointer;
  font-family: var(--sans); text-align: left;
}
.mobile .acc-btn svg { transition: transform .2s var(--ease); }
.mobile .acc-btn[aria-expanded="true"] svg { transform: rotate(180deg); }
.mobile .acc-panel { display: none; padding: 4px 0 12px 14px; border-left: 2px solid var(--galad); margin: 10px 0 10px 2px; }
.mobile .acc-panel.open { display: block; }
.mobile .acc-panel a { display: block; padding: 10px 0; font-size: 15.5px; color: var(--body); text-decoration: none; }
.mobile .acc-panel a:hover { color: var(--galad-ink); }
.mobile .btn { width: 100%; margin-top: 24px; }

/* --------------------------------------------------------------------------
   7. Opening brand animation
   -------------------------------------------------------------------------- */
#intro {
  position: fixed; inset: 0; z-index: 999; background: #FFFFFF;
  display: flex; align-items: center; justify-content: center;
}
#intro.done { opacity: 0; visibility: hidden; transition: opacity .5s var(--ease), visibility .5s; }

/* The supplied logo is the whole animation. Nothing is drawn around it except
   a hairline ring and a soft glow, both sitting outside the artwork. */
.intro-lockup { position: relative; width: min(281px, 66vw); will-change: transform; }
.intro-draw { display: block; width: 100%; height: auto; }

/* Nothing is visible when the overlay first paints. Each element is brought in
   by the script, in order. These are the resting states, set here rather than
   in script so nothing can flash before the animation starts. */
.intro-disc { opacity: 0; transform-origin: 120.2px 107.7px; }
.intro-g, .intro-glow, .intro-shadow { opacity: 0; }

/* The dash lengths are generous so the strokes sit entirely inside their gaps
   until the script measures the real path lengths. */
.draw-path { stroke-dasharray: 400 402; stroke-dashoffset: 401; }
.wipe { stroke-dasharray: 300 302; stroke-dashoffset: 301; }
body.intro-active { overflow: hidden; }
body.intro-active .page { opacity: 0; }
.page { transition: opacity .6s var(--ease); }

/* --------------------------------------------------------------------------
   7a. Opening animation, phones only

   Everything above is the desktop intro and is untouched. Above 767px the
   lockup rule resolves to a flat 248px, because 58vw only ever wins below
   about 428px, so nothing in this block can reach the desktop layout.

   The problem on phones was scale, not proportion: at 320px the lockup fell to
   186px, which left the "Accounting and Tax" band about 14px tall and made the
   whole mark look cramped. The logo is one SVG with a fixed viewBox, so it can
   only ever scale as a unit. Nothing here stretches an axis, and there is no
   scaleX anywhere in the project.
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
  #intro {
    /* padding guarantees the 20px side gutters; overflow clips rather than
       ever producing a horizontal scrollbar */
    padding: 24px max(20px, env(safe-area-inset-left)) 24px max(20px, env(safe-area-inset-right));
    overflow: hidden;
    min-height: 100vh;
    min-height: 100svh;   /* the small viewport, so the URL bar cannot crop it */
  }

  .intro-lockup {
    /* the plain value first, so a browser without svh keeps a working layout */
    width: min(88vw, 374px);
    /* 0.9414 is 273/290, the lockup's own ratio, so the third term caps the
       width by the height available. This is what stops a landscape phone
       cropping the logo. The first two terms are the previous 78vw/330px
       scaled by 273/241, so the visible circle is the same size as before
       while the SVG now carries its own safe margin. */
    width: min(88vw, 374px, calc((100svh - 56px) * 0.9414));
    max-width: calc(100vw - 40px);
    margin-inline: auto;
    flex-shrink: 0;       /* the flex parent can never squeeze it */
  }

  .intro-draw {
    width: 100%;
    height: auto;
    aspect-ratio: 273 / 290;   /* the viewBox ratio, stated rather than implied */
  }
}

/* --------------------------------------------------------------------------
   8. Hero
   -------------------------------------------------------------------------- */
.hero { background: var(--ink); color: var(--muted-dark); overflow: hidden; position: relative; }
.hero::after {
  content: ""; position: absolute; right: -12%; top: -30%; width: 780px; height: 780px;
  background: radial-gradient(circle at center, rgba(230,23,54,.16), rgba(230,23,54,0) 62%);
  pointer-events: none;
}
.hero-inner { position: relative; z-index: 1; padding: clamp(64px, 7vw, 104px) 0 clamp(64px, 7vw, 96px); }
.hero h1 { color: #fff; margin-bottom: 22px; }
.hero h1 em { font-style: italic; color: #fff; }
.hero .lead { font-size: clamp(17px, 1.5vw, 20px); color: #C8CCD3; max-width: 54ch; }
.hero-meta {
  display: flex; flex-wrap: wrap; gap: 10px 26px; margin-top: 34px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted-dark);
}
.hero-meta span { display: flex; align-items: center; gap: 9px; }
.hero-meta span::before { content: ""; width: 5px; height: 5px; background: var(--galad); flex: none; }

/* Signature element: the statement card.
   A familiar artefact from the client's world, a ruled statement of account,
   rebuilt as the hero's navigation object. No figures, nothing invented. */
.statement {
  background: #fff; border-radius: var(--radius); box-shadow: var(--shadow-lg);
  overflow: hidden; color: var(--body);
}
.statement-top {
  background: linear-gradient(135deg, var(--galad) 0%, var(--galad-deep) 100%);
  color: #fff; padding: 22px 26px; display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.statement-top .t { font-family: var(--display); font-size: 21px; line-height: 1.2; }
.statement-top .n { font-family: var(--mono); font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase; opacity: .85; }
.statement-rows { padding: 6px 26px 8px; }
.statement-rows a {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 15px 0; border-bottom: 1px solid var(--line); text-decoration: none;
  color: var(--ink); font-size: 15.5px; font-weight: 500;
  transition: color .18s var(--ease), padding-left .18s var(--ease);
}
.statement-rows a:hover { color: var(--galad-ink); padding-left: 5px; }
.statement-rows a span { font-family: var(--mono); font-size: 11px; color: var(--muted); letter-spacing: .1em; }
.statement-rows a:hover span { color: var(--galad); }
.statement-foot { margin: 0 26px; padding: 20px 0 26px; border-top: 2px solid var(--ink); }
.statement-foot p { font-size: 13.5px; color: var(--muted); margin-bottom: 14px; }
.statement-foot .btn { width: 100%; }

/* --------------------------------------------------------------------------
   9. Page hero (interior pages)
   -------------------------------------------------------------------------- */
.pagehead { background: var(--ink); color: var(--muted-dark); position: relative; overflow: hidden; }
.pagehead::after {
  content: ""; position: absolute; left: 50%; bottom: -60%; width: 620px; height: 620px;
  background: radial-gradient(circle at center, rgba(230,23,54,.14), rgba(230,23,54,0) 60%);
  pointer-events: none;
}
.pagehead-inner { position: relative; z-index: 1; padding: clamp(52px, 6vw, 84px) 0 clamp(48px, 5.5vw, 72px); }
.pagehead h1 { color: #fff; max-width: 18ch; }
.pagehead .lead { color: #C8CCD3; }
.crumb {
  font-family: var(--mono); font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted-dark); margin-bottom: 22px;
}
.crumb a { color: var(--muted-dark); text-decoration: none; }
.crumb a:hover { color: #fff; }
.crumb i { font-style: normal; color: var(--galad); margin: 0 8px; }

/* --------------------------------------------------------------------------
   10. Tiles and lists
   -------------------------------------------------------------------------- */
.tile {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 28px 26px 30px; position: relative;
  transition: border-color .22s var(--ease), transform .22s var(--ease), box-shadow .22s var(--ease);
}
.tile::before {
  content: ""; position: absolute; left: -1px; top: -1px; width: 0; height: 3px;
  background: var(--galad); transition: width .3s var(--ease);
}
.tile:hover { border-color: #D2D5DB; transform: translateY(-3px); box-shadow: var(--shadow-md); }
.tile:hover::before { width: 46px; }
.tile h3 { margin-bottom: 10px; }
.tile p { font-size: 15px; margin: 0; }
.tile .ico { color: var(--galad); margin-bottom: 18px; }
.tile a.tile-link { position: absolute; inset: 0; text-indent: -9999px; overflow: hidden; }
.s-mist .tile { background: #fff; }
.s-ink .tile { background: var(--slate); border-color: var(--graphite); }
.s-ink .tile p { color: var(--muted-dark); }
.s-ink .tile:hover { border-color: #3A3E47; }

.tick { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.tick li { position: relative; padding-left: 28px; font-size: 15.5px; }
.tick li::before {
  content: ""; position: absolute; left: 0; top: 9px; width: 12px; height: 6px;
  border-left: 2px solid var(--galad); border-bottom: 2px solid var(--galad);
  transform: rotate(-45deg);
}
.tick-2 { display: grid; gap: 11px; }
@media (min-width: 700px) { .tick-2 { grid-template-columns: 1fr 1fr; gap: 11px 32px; } }

/* Service detail blocks */
.detail { display: grid; gap: 14px 40px; padding: 34px 0; border-top: 1px solid var(--line); }
@media (min-width: 860px) { .detail { grid-template-columns: 300px 1fr; } }
.detail:last-of-type { border-bottom: 1px solid var(--line); }
.detail h3 { margin: 0; }
.detail .num { font-family: var(--mono); font-size: 11px; color: var(--galad); letter-spacing: .16em; display: block; margin-bottom: 8px; }
.detail p { font-size: 15.5px; margin-bottom: 14px; }

/* Process */
.steps { counter-reset: s; display: grid; gap: 2px; }
.step { display: grid; gap: 6px 28px; padding: 30px 0; border-top: 1px solid var(--line); position: relative; }
@media (min-width: 800px) { .step { grid-template-columns: 90px 260px 1fr; align-items: start; } }
.step .idx { font-family: var(--mono); font-size: 12px; color: var(--galad); letter-spacing: .14em; padding-top: 4px; }
.step h3 { margin: 0; }
.step p { margin: 0; font-size: 15.5px; }
.s-ink .step { border-color: var(--graphite); }

/* FAQ */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  list-style: none; cursor: pointer; padding: 24px 44px 24px 0; position: relative;
  font-size: 17px; font-weight: 500; color: var(--ink); font-family: var(--sans);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: 6px; top: 32px; width: 11px; height: 11px;
  border-right: 2px solid var(--galad); border-bottom: 2px solid var(--galad);
  transform: rotate(45deg); transition: transform .22s var(--ease);
}
.faq details[open] summary::after { transform: rotate(-135deg); top: 36px; }
.faq .ans { padding: 0 60px 26px 0; font-size: 15.5px; }
.faq .ans p:last-child { margin-bottom: 0; }

/* Testimonials, clearly marked as placeholders until real ones are supplied */
.quote {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 30px 28px; position: relative;
}
.quote::before { content: ""; position: absolute; left: 28px; top: 0; width: 34px; height: 3px; background: var(--galad); }
.quote p { font-family: var(--display); font-size: 20px; line-height: 1.45; color: var(--ink); }
.quote .who { font-size: 13.5px; color: var(--muted); margin-top: 18px; font-family: var(--sans); }

/* Team */
.person { border-top: 2px solid var(--galad); padding-top: 26px; max-width: 420px; }
.person + .person { margin-top: 36px; }
.person h3 {
  font-family: var(--display); font-weight: 400; letter-spacing: -.01em;
  font-size: clamp(26px, 2.4vw, 32px); line-height: 1.1; margin: 0 0 9px;
}
.person p {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--muted); margin: 0;
}

/* Addresses */
address { font-style: normal; line-height: 1.7; }
.eircode {
  display: inline-block; font-family: var(--mono); font-weight: 500;
  letter-spacing: .14em; color: var(--ink); margin-top: 3px;
}
.foot-addr .eircode { color: #fff; }
.addr { font-size: 16px; color: var(--ink); }
.foot-addr { font-size: 14.5px; color: var(--muted-dark); margin: 18px 0 0; }
.foot-hours { font-size: 14.5px; color: var(--muted-dark); margin: 10px 0 0; }

/* --------------------------------------------------------------------------
   11. Booking and CTA
   -------------------------------------------------------------------------- */
.booking {
  background: linear-gradient(150deg, var(--slate) 0%, var(--ink) 55%, #1D1114 100%);
  border-radius: var(--radius); padding: clamp(34px, 4.5vw, 56px); position: relative; overflow: hidden;
}
.booking::before {
  content: ""; position: absolute; right: -90px; top: -90px; width: 340px; height: 340px;
  border: 44px solid rgba(230, 23, 54, .13); border-radius: 50%;
}
.booking > * { position: relative; z-index: 1; }
.booking h2 { color: #fff; }
.booking .lead { color: #C8CCD3; }

.cal-embed {
  background: #fff; border-radius: var(--radius); min-height: 320px; margin-top: 30px;
  display: flex; align-items: center; justify-content: center; text-align: center; padding: 40px 26px;
}
.cal-embed .inner { max-width: 460px; }
.cal-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 22px; }
.cal-embed h4 { margin-bottom: 8px; }
.cal-embed p { font-size: 14.5px; color: var(--muted); }

.cta-band { background: var(--ink); color: var(--muted-dark); }
.cta-band h2 { color: #fff; }
.cta-split { display: grid; gap: 30px; align-items: center; }
@media (min-width: 900px) { .cta-split { grid-template-columns: 1.2fr auto; } }

/* --------------------------------------------------------------------------
   12. Forms
   -------------------------------------------------------------------------- */
.form-card {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: clamp(26px, 3.5vw, 40px); box-shadow: var(--shadow-sm);
}

/* Wrapper for the GoHighLevel iframe. The embedded form brings its own
   internal padding, so the card padding is trimmed to avoid a double inset,
   and the height is left to form_embed.js. min-height only prevents a
   collapse to the iframe's 150px default before that script has run;
   overflow stays visible so nothing is clipped and no second scrollbar
   appears over the form's own. */
.form-card-embed {
  padding: 10px;
  overflow: visible;
}
.form-card-embed iframe {
  display: block;
  width: 100%;
  max-width: 100%;
  /* 946px is the height GHL reports for this form in data-height, so the
     placeholder matches the final height and nothing jumps when the script
     resizes. */
  min-height: 946px;
  border: 0;
}
@media (max-width: 700px) {
  .form-card-embed { padding: 6px; }
  /* stacked fields make the form taller on a narrow screen */
  .form-card-embed iframe { min-height: 1080px; }
}
.field { margin-bottom: 20px; }
.field label { display: block; font-size: 13.5px; font-weight: 600; color: var(--ink); margin-bottom: 7px; }
.field label .req { color: var(--galad); }
.field input, .field select, .field textarea {
  width: 100%; font-family: var(--sans); font-size: 15.5px; color: var(--ink);
  padding: 13px 14px; background: #fff; border: 1px solid var(--line);
  border-radius: var(--radius); transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.field textarea { min-height: 132px; resize: vertical; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: #CDD1D8; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--galad); box-shadow: 0 0 0 3px rgba(230, 23, 54, .12);
}
.field.err input, .field.err select, .field.err textarea { border-color: var(--galad); background: var(--galad-wash); }
.field .msg { display: none; font-size: 13px; color: var(--galad-ink); margin-top: 6px; font-weight: 500; }
.field.err .msg { display: block; }
.field-2 { display: grid; gap: 0 20px; }
@media (min-width: 700px) { .field-2 { grid-template-columns: 1fr 1fr; } }

.check { display: flex; gap: 12px; align-items: flex-start; font-size: 14px; color: var(--body); }
.check input { width: 18px; height: 18px; margin-top: 2px; flex: none; accent-color: var(--galad); }
.check a { color: var(--galad-ink); }

.form-note { font-size: 13px; color: var(--muted); margin-top: 18px; }

.alert { border-radius: var(--radius); padding: 16px 18px; font-size: 15px; margin-bottom: 22px; display: none; }
.alert.show { display: block; }
.alert-ok { background: #ECF7F0; border: 1px solid #B9E0C8; color: #1B5E37; }
.alert-err { background: var(--galad-wash); border: 1px solid rgba(230,23,54,.3); color: var(--galad-ink); }

/* --------------------------------------------------------------------------
   13. Contact details, hours
   -------------------------------------------------------------------------- */
.info-list { list-style: none; margin: 0; padding: 0; }
.info-list li { padding: 18px 0; border-bottom: 1px solid var(--line); }
.info-list .k {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted); display: block; margin-bottom: 6px;
}
.info-list .v { font-size: 16px; color: var(--ink); font-weight: 500; }
.info-list .addr { font-size: 16px; color: var(--ink); font-weight: 500; }
.info-list a { color: var(--ink); text-decoration: none; }
.info-list a:hover { color: var(--galad-ink); }

.map-embed {
  border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; background: var(--mist);
}
.map-embed iframe { display: block; width: 100%; height: 360px; border: 0; }
@media (max-width: 700px) { .map-embed iframe { height: 260px; } }

/* --------------------------------------------------------------------------
   14. Legal pages
   -------------------------------------------------------------------------- */
.prose { max-width: 74ch; }
.prose h2 { font-size: clamp(24px, 2.2vw, 30px); margin-top: 48px; }
.prose h3 { margin-top: 32px; }
.prose ul { padding-left: 20px; }
.prose li { margin-bottom: 8px; }
.prose .stamp {
  font-family: var(--mono); font-size: 12px; color: var(--muted);
  border-left: 2px solid var(--galad); padding-left: 14px; margin-bottom: 40px;
}
.notice {
  background: var(--galad-wash); border: 1px solid rgba(230,23,54,.25);
  border-radius: var(--radius); padding: 20px 22px; font-size: 14.5px; color: var(--galad-ink);
}
.notice strong { display: block; margin-bottom: 4px; color: var(--galad-ink); }

/* --------------------------------------------------------------------------
   15. Footer
   -------------------------------------------------------------------------- */
.site-footer { background: var(--ink); color: var(--muted-dark); padding: clamp(56px, 6vw, 80px) 0 34px; }
.site-footer h4 {
  color: #fff; font-family: var(--mono); font-size: 11px; letter-spacing: .18em;
  text-transform: uppercase; font-weight: 500; margin-bottom: 18px;
}
.foot-grid { display: grid; gap: 40px; }
@media (min-width: 760px) { .foot-grid { grid-template-columns: 1.4fr 1fr 1fr 1.2fr; gap: 40px 30px; } }
.foot-brand .brand .wordmark b { color: #fff; }
.foot-brand .brand .wordmark span { color: var(--muted-dark); }
.foot-brand p { font-size: 14.5px; margin-top: 20px; max-width: 34ch; }
.foot-links { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.foot-links a { font-size: 14.5px; color: var(--muted-dark); text-decoration: none; transition: color .18s var(--ease); }
.foot-links a:hover { color: #fff; }
.foot-bottom {
  margin-top: 54px; padding-top: 26px; border-top: 1px solid var(--graphite);
  display: flex; flex-wrap: wrap; gap: 14px 28px; align-items: center; justify-content: space-between;
  font-size: 13px; color: var(--muted-dark);
}
.foot-bottom a { color: var(--muted-dark); text-decoration: none; }
.foot-bottom a:hover { color: #fff; }
.foot-legal { display: flex; flex-wrap: wrap; gap: 8px 20px; }

/* --------------------------------------------------------------------------
   16. Motion
   -------------------------------------------------------------------------- */
.rv { opacity: 0; transform: translateY(18px); }
.rv.in { opacity: 1; transform: none; transition: opacity .7s var(--ease), transform .7s var(--ease); }
.rv-d1.in { transition-delay: .08s; }
.rv-d2.in { transition-delay: .16s; }
.rv-d3.in { transition-delay: .24s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .rv { opacity: 1; transform: none; }
  /* The intro is deliberately untouched here. It is built from Web Animations
     API calls whose timing lives in script, not in animation-duration, so the
     override above cannot shorten it. The full sequence plays with Reduce
     Motion on, which is what was asked for. */
}

/* --------------------------------------------------------------------------
   16a. Phone layout

   Root cause of the cramped mobile homepage: the fluid type scale has
   desktop-sized floors. h1 is clamp(40px, 5.6vw, 68px) and h2 is
   clamp(31px, 3.7vw, 46px), but the vw term does not overtake 40px until the
   viewport is 714px wide, and does not overtake 31px until 838px. Below those
   widths both headings sit permanently on their floor and never scale, so a
   375px phone renders the same 40px display type that was drawn for a 1440px
   desktop. Desktop gets about 37 characters per line, a 320px phone gets 15.
   Everything downstream then has to make room for type that is more than twice
   as large relative to its column, which is what reads as crowded, clipped and
   squeezed.

   The fix is to give the phone range its own floors. The ceilings are set so
   the two scales meet exactly at the breakpoint: at 767px this block resolves
   to 43px and 31px, which is precisely what the desktop rules already produce
   at 768px. Nothing here can reach a viewport of 768px or wider.
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {

  /* A net, not the fix. The audit found no element that overflows: the three
     wide decorative circles are all inside overflow-hidden parents, .drop is
     inside .nav which is display:none below 1060px, and there are no negative
     margins or 100vw widths in the layout. clip is used rather than hidden so
     the sticky header keeps working. */
  html { max-width: 100%; overflow-x: clip; }

  /* 1. the actual correction: a type scale with phone-sized floors */
  h1 { font-size: clamp(30px, 8.2vw, 43px); line-height: 1.12; letter-spacing: -.02em; }
  h2 { font-size: clamp(25px, 6.4vw, 31px); line-height: 1.14; }
  .person h3 { font-size: clamp(22px, 4vw, 26px); }

  /* 2. grid and flex children default to min-width:auto, which lets a wide
        child force its track wider than the screen. Nothing does today, but
        this removes the possibility. */
  .cols > *, .grid > *, .cta-split > *, .foot-grid > *,
  .statement-rows a, .hero-meta span { min-width: 0; }

  /* 3. buttons stacked and full width across the whole phone range, not just
        below 430px, and allowed to wrap rather than staying nowrap */
  .btn { white-space: normal; padding: 15px 20px; }
  .btn-row { gap: 14px; margin-top: 28px; }
  .btn-row .btn, .cal-actions .btn { width: 100%; }

  /* 4. the row of small capitals under the hero was 11.5px with .12em tracking,
        which is legible on a desktop and not on a phone */
  .hero-meta { gap: 12px 20px; margin-top: 30px; font-size: 12px; letter-spacing: .08em; }

  /* 5. a little more air around the headings now that they are smaller */
  .hero h1 { margin-bottom: 20px; }
  .head { margin-bottom: 34px; }
  .hero-inner { padding: 56px 0 48px; }
  /* ===== MOBILE HEADER ===== */

:root {
  --gut: 20px;
  --sec: 64px;
  --hdr-h: 70px;
}

body {
  font-size: 16px;
  line-height: 1.6;
}

.wrap {
  width: 100%;
  max-width: 100%;
  /* the 18-20px gutter asked for, widened only where a notch intrudes */
  padding-left: max(20px, env(safe-area-inset-left));
  padding-right: max(20px, env(safe-area-inset-right));
}

.hdr {
  gap: 10px;
}

.brand {
  gap: 8px;
  min-width: 0;
  max-width: calc(100% - 58px);
}

.brand .markwrap {
  flex: 0 0 auto;
}

.brand .mark {
  width: 42px;
  height: 42px;
  object-fit: contain;
}

.brand .wordmark {
  min-width: 0;
  overflow: hidden;
}

.brand .wordmark b {
  font-size: 22px;
  white-space: nowrap;
}

.brand .wordmark span {
  font-size: 7px;
  letter-spacing: 0.13em;
  white-space: nowrap;
}

.burger {
  width: 44px;
  height: 44px;
  flex: 0 0 44px;
}
/* ===== MOBILE MENU ===== */

.mobile .wrap {
  min-height: 100%;
  padding-bottom: 50px;
}

.mobile .wrap > a,
.mobile .acc-btn {
  padding: 18px 0;
  font-size: 16px;
}

.mobile .acc-panel {
  margin: 8px 0 12px;
}

.mobile .acc-panel a {
  padding: 12px 0;
  font-size: 15px;
}

/* ===== MOBILE HERO ===== */

.hero {
  overflow: hidden;
}

.hero-inner {
  width: 100%;
  padding-top: 46px;
  padding-bottom: 52px;
}

.hero-inner > .cols {
  display: block;
  width: 100%;
  max-width: 100%;
}

.hero-inner > .cols > * {
  width: 100%;
  max-width: 100%;
  min-width: 0;
}

.hero .eyebrow {
  margin-bottom: 22px;
  font-size: 10.5px;
  letter-spacing: 0.13em;
}

.hero h1 {
  width: 100%;
  max-width: 100%;
  margin-left: 0;
  margin-right: 0;
  margin-bottom: 24px;

  font-size: clamp(34px, 9.5vw, 43px);
  line-height: 1.07;
  letter-spacing: -0.025em;

  white-space: normal;
  overflow-wrap: normal;
}

.hero .lead {
  width: 100%;
  max-width: 100%;
  margin-top: 0;

  font-size: 16px;
  line-height: 1.65;
}

.hero .btn-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;

  width: 100%;
  margin-top: 30px;
}

.hero .btn-row .btn {
  width: 100%;
  min-height: 54px;
}

.hero-meta {
  display: grid;
  grid-template-columns: 1fr;
  gap: 13px;

  width: 100%;
  margin-top: 34px;

  font-size: 11px;
  line-height: 1.5;
  letter-spacing: 0.08em;
}

.statement {
  width: 100%;
  max-width: 100%;
  margin-top: 44px;
}

.statement-top {
  padding: 20px;
}

.statement-rows {
  padding-left: 20px;
  padding-right: 20px;
}

.statement-foot {
  margin-left: 20px;
  margin-right: 20px;
}

/* ===== MOBILE SECTIONS ===== */

.band {
  padding-top: 64px;
  padding-bottom: 64px;
}

.head {
  margin-bottom: 34px;
}

.cols {
  gap: 36px;
}

.grid {
  gap: 18px;
}

.tile {
  padding: 25px 21px 27px;
}
}

/* --------------------------------------------------------------------------
   17. Print
   -------------------------------------------------------------------------- */
@media print {
  .site-header, .mobile, #intro, .booking, .cta-band { display: none !important; }
  body { color: #000; font-size: 12pt; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
}

/* ==========================================================================
   GALAD CHATBOT
   Appended as a self-contained block. Every selector below is scoped to an
   id or a galad-chat/galad-message class, so nothing above is affected and
   no generic element is restyled. Fixed positioning is used for the
   launcher and the panel only. No rule here touches body, html, scrolling,
   or the mobile menu.
   ========================================================================== */

#galad-chat-launcher {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 120;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 58px;
  height: 58px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: #25d366;
  color: #fff;
  cursor: pointer;
  box-shadow: 0 14px 35px rgba(0, 0, 0, .18);

  /* The hover scale lives here as a variable because the bubble below has to
     cancel it exactly. Change it in one place and both stay in step. */
  --pop: 1.08;
  transform-origin: center;
  transition:
    transform .22s var(--ease),
    background .22s var(--ease),
    box-shadow .25s var(--ease);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  /* No clipping is set on this button on purpose. The hover bubble is an
     absolutely positioned child that sits outside the button's own box, so
     clipping here would hide it entirely. */
}

#galad-chat-launcher:hover {
  background: #1ebe5b;
  box-shadow: 0 18px 42px rgba(0, 0, 0, .22);
}

#galad-chat-launcher:hover,
#galad-chat-launcher:focus-visible {
  transform: scale(var(--pop));
}

#galad-chat-launcher:active {
  transform: scale(1.04);
}

.galad-chat-launcher-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;

  width: 46px;
  height: 46px;

  border-radius: 50%;

  font-family: var(--display);
  font-size: 25px;
  line-height: 1;
  color: #fff;

  transition: text-shadow .3s var(--ease);
}

/* Glow only. No transform, so the mark does not change size. */
#galad-chat-launcher:hover .galad-chat-launcher-icon,
#galad-chat-launcher:focus-visible .galad-chat-launcher-icon {
  text-shadow:
    0 0 5px rgba(255, 255, 255, .95),
    0 0 12px rgba(255, 255, 255, .7),
    0 0 20px rgba(255, 255, 255, .4);
}

/* The launcher is now a WhatsApp link rather than a button. */
a#galad-chat-launcher {
  text-decoration: none;
}

/* Keep the focus ring WhatsApp green instead of the brand red. */
#galad-chat-launcher:focus-visible {
  outline-color: #25d366;
}

.galad-chat-launcher-icon svg {
  display: block;
  width: 30px;
  height: 30px;
  transition: filter .3s var(--ease);
}

#galad-chat-launcher:hover .galad-chat-launcher-icon svg,
#galad-chat-launcher:focus-visible .galad-chat-launcher-icon svg {
  filter: drop-shadow(0 0 6px rgba(255, 255, 255, .8));
}

.galad-chat-hover-message {
  position: absolute;

  /* Place the bubble diagonally above-left of the launcher */
  right: calc(100% + 14px);
  bottom: calc(100% - 10px);

  width: max-content;
  max-width: 230px;
  padding: 10px 14px;

  border: 1px solid rgba(0, 0, 0, .08);
  border-radius: 13px;
  background: #fff;
  color: var(--ink);

  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.35;
  text-align: left;
  white-space: nowrap;

  box-shadow: 0 12px 30px rgba(0, 0, 0, .14);

  opacity: 0;
  visibility: hidden;
  pointer-events: none;

  /* This bubble is a child of the button, so the button's hover scale would
     enlarge it and push it further out along the diagonal. Anchoring the
     origin on the CIRCLE's centre and applying the inverse scale cancels the
     parent's transform exactly, so the bubble keeps its size and its place.
     43px and 19px are the offsets from this bubble's bottom-right corner to
     the centre of the 58px circle, both fixed by the right/bottom values
     above and so independent of how wide the text runs. */
  transform-origin: calc(100% + 43px) calc(100% + 19px);
  transform: translate(8px, 8px) scale(calc(1 / var(--pop)));
  transition:
    opacity .2s var(--ease),
    transform .24s var(--ease),
    visibility .2s;
}

.galad-chat-hover-message::after {
  content: "";
  position: absolute;

  /* Tail sits at the lower-right corner and points towards the circle */
  right: 12px;
  bottom: -7px;

  width: 13px;
  height: 13px;

  background: #fff;
  border-right: 1px solid rgba(0, 0, 0, .08);
  border-bottom: 1px solid rgba(0, 0, 0, .08);

  transform: rotate(45deg);
}

#galad-chat-launcher:hover .galad-chat-hover-message,
#galad-chat-launcher:focus-visible .galad-chat-hover-message {
  opacity: 1;
  visibility: visible;
  transform: translate(0, 0) scale(calc(1 / var(--pop)));
}

/* While the panel is open the bubble stays down, even on hover. The
   .is-closing half covers the case where the launcher itself was used to
   close: aria-expanded flips to false straight away, and without this the
   bubble would flash back in under the cursor while the panel is still
   shrinking. Same specificity as the rule above, so it is placed after it. */
#galad-chat-launcher[aria-expanded="true"] .galad-chat-hover-message,
#galad-chat-launcher.is-closing .galad-chat-hover-message {
  opacity: 0 !important;
  visibility: hidden !important;
  pointer-events: none;
  transform: translate(8px, 8px) scale(calc(1 / var(--pop)));
}

/* Touch and narrow screens: the circle only, no bubble, no hover needed. */
@media (hover: none), (pointer: coarse), (max-width: 767px) {
  #galad-chat-launcher {
    right: 16px;
    bottom: max(18px, env(safe-area-inset-bottom));
  }

  .galad-chat-hover-message {
    display: none;
  }
}

.galad-chat-panel {
  position: fixed;
  right: 24px;
  bottom: 96px;
  z-index: 121;
  width: min(390px, calc(100vw - 32px));
  height: min(600px, calc(100dvh - 130px));
  overflow: hidden;
  border: 1px solid rgba(0, 0, 0, .1);
  border-radius: 20px;
  background: var(--paper);
  box-shadow: 0 25px 70px rgba(0, 0, 0, .22);

  /* Closed resting state. The panel expands from the corner closest to the
     launcher, and the translate carries it the rest of the way down and
     right, so it reads as growing out of the G rather than fading in place. */
  transform-origin: bottom right;
  opacity: 0;
  transform: translate(24px, 24px) scale(.88);
  transition:
    opacity .3s var(--ease),
    transform .3s var(--ease);
}

.galad-chat-panel.is-open {
  opacity: 1;
  transform: translate(0, 0) scale(1);
}

/* The reverse. pointer-events is dropped so a second click during the
   300ms close cannot land on the fading panel. */
.galad-chat-panel.is-closing {
  opacity: 0;
  transform: translate(24px, 24px) scale(.88);
  pointer-events: none;
}

/* Kept, so the panel leaves the layout once the close animation has run.
   It is applied by script after the transition, never during it. */
.galad-chat-panel[hidden] {
  display: none;
}

.galad-chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 74px;
  padding: 16px 18px;
  background: var(--ink);
  color: #fff;
}

.galad-chat-header > div {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.galad-chat-header strong {
  font-size: 16px;
  font-weight: 600;
}

.galad-chat-header span {
  font-size: 12px;
  opacity: .72;
}

#galad-chat-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  background: transparent;
  color: #fff;
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.galad-chat-messages {
  height: calc(100% - 150px);
  padding: 16px 14px;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  background: #F7F7F5;
}

.galad-message {
  position: relative;
  width: fit-content;
  max-width: 78%;
  margin-bottom: 14px;
  padding: 10px 13px;
  border-radius: 18px;
  font-size: 14.5px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  text-align: left;
}

/* The welcome bubble is the only message written into the page as markup.
   Every other message is inserted with textContent, which carries no stray
   whitespace. Because .galad-message uses white-space: pre-wrap, the source
   indentation of that one bubble was being rendered literally: a blank line
   above the text, six spaces before "Welcome", and a blank line below. That
   is the extra height and the left indent, and it is content rather than
   padding, so no padding value could remove it. Collapsing whitespace on the
   first bubble only leaves every later message's line breaks intact. */
.galad-chat-messages > .galad-message:first-child {
  white-space: normal;
}

.galad-message-bot {
  margin-right: auto;
  margin-left: 0;
  background: #fff;
  color: var(--ink);
  border: 1px solid rgba(0, 0, 0, .07);
  border-bottom-left-radius: 5px;
}

.galad-message-bot::after {
  content: "";
  position: absolute;
  left: -6px;
  bottom: 0;
  width: 14px;
  height: 14px;
  background: #fff;
  border-bottom-right-radius: 12px;
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}

.galad-message-user {
  margin-left: auto;
  margin-right: 0;
  background: var(--galad);
  color: #fff;
  border-bottom-right-radius: 5px;
}

.galad-message-user::after {
  content: "";
  position: absolute;
  right: -6px;
  bottom: 0;
  width: 14px;
  height: 14px;
  background: var(--galad);
  border-bottom-left-radius: 12px;
  clip-path: polygon(0 0, 100% 100%, 0 100%);
}

.galad-message-status {
  font-size: 13px;
  color: var(--muted);
  background: transparent;
  border: 0;
  padding-left: 0;
}

/* Quick actions. The wrapper is an ordinary bot bubble, so it keeps the
   existing white fill, border, radius and lower-left tail. The buttons reuse
   the panel's own ink and red rather than introducing any new colour. */
.galad-message-actions {
  max-width: 100%;
  padding: 10px 11px;
}

.galad-chat-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.galad-chat-action {
  border: 1px solid rgba(0, 0, 0, .14);
  border-radius: 999px;
  padding: 7px 12px;
  background: #fff;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: background .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.galad-chat-action:hover,
.galad-chat-action:focus-visible {
  background: var(--galad);
  border-color: var(--galad);
  color: #fff;
}

/* Typing indicator. It is an ordinary bot bubble, so it inherits the existing
   white fill, border, radius and lower-left tail without restating any of
   them. Only the padding is trimmed, because three dots do not need the room
   a line of text does. */
.galad-message-typing {
  padding: 13px;
}

.galad-chat-typing {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.galad-chat-typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--muted);
  animation: galadTypingDot 1.1s infinite ease-in-out;
}

.galad-chat-typing span:nth-child(2) { animation-delay: .15s; }
.galad-chat-typing span:nth-child(3) { animation-delay: .3s; }

/* 3px of travel: enough to read as typing, small enough not to be a
   distraction beside the text it sits next to. */
@keyframes galadTypingDot {
  0%, 60%, 100% { transform: translateY(0); opacity: .5; }
  30%           { transform: translateY(-3px); opacity: 1; }
}

/* The sheet already has a global reduce block that forces every animation to
   .001ms with one iteration. On its own that would leave the dots parked on
   the closing keyframe, which is opacity .5, so all three would sit dim.
   Naming the animation off and restoring full opacity gives three solid,
   still dots instead. animation-name is not marked important in the global
   rule, so this class selector carries it. */
@media (prefers-reduced-motion: reduce) {
  .galad-chat-typing span {
    animation: none;
    opacity: 1;
  }
}

.galad-message-status::after {
  display: none;
}

.galad-chat-form {
  display: flex;
  gap: 8px;
  min-height: 76px;
  padding: 12px 12px 18px;
  background: #fff;
  border-top: 1px solid rgba(0, 0, 0, .08);
}

.galad-chat-form input {
  flex: 1;
  min-width: 0;
  border: 1px solid rgba(0, 0, 0, .15);
  border-radius: 12px;
  padding: 0 13px;
  color: var(--ink);
  background: #fff;
  font: inherit;
}

.galad-chat-form input:disabled {
  opacity: .65;
}

.galad-chat-form button {
  border: 0;
  border-radius: 12px;
  padding: 0 17px;
  background: var(--galad);
  color: #fff;
  font-family: var(--sans);
  font-weight: 600;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.galad-chat-form button:disabled {
  cursor: wait;
  opacity: .65;
}

@media (max-width: 767px) {
  .galad-chat-panel {
    right: 12px;
    bottom: calc(88px + env(safe-area-inset-bottom));
    width: calc(100vw - 24px);
    height: min(620px, calc(100dvh - 110px));
  }
}
