/* ============================================================================
   Ikerd Law 2026 — WordPress-only styles.

   home.css is kept byte-identical to the mockup's <style> block so it can be
   re-synced from html/index.html. Everything WordPress or the house rules make
   necessary lives here instead:

   1. Classes replacing the mockup's inline style="" attributes (no inline CSS
      is allowed in the source or at runtime).
   2. A Gravity Forms bridge so form markup inherits the mockup's form design.
   3. Admin-bar and editor-preview corrections.
   ========================================================================= */

/* ---------- 1. de-inlined utilities ---------------------------------------
   Each rule below replaces one style="" attribute in html/index.html. The
   comment names the section it came from. */

/* The mockup ran the first CTA block flush to the section above it
   (style="padding-top:0"). That put the paper/paper2 colour seam exactly on the
   navy box's top edge, so the box read as sitting on the join. It now uses the
   page's normal 58px section rhythm, which is why no --flush-top class remains. */
.sec--flush-bottom { padding-bottom: 0 }         /* CTA block before the FAQ */

.gap-top           { margin-top: 1.6em }         /* "what we handle" + reviews grids */
.steps             { margin-top: 1.5em }         /* "what happens in the first call" */
.faq-list          { margin-top: 1.5em }         /* FAQ accordion stack */
.lede--gap         { margin-bottom: 1.6em }      /* first 72 hours */
.lede--gap-sm      { margin-bottom: 1.5em }      /* law explained, penalties, job worries */
.fine--gap         { margin-top: 1.4em }         /* trailing fine print in several sections */
.link--gap         { margin-top: 1.4em }         /* "read all reviews on Google" */
.note--gap         { margin-top: 1.3em }         /* "not sure which parish" */

.narrow--center    { text-align: center }        /* reassurance + final CTA bands */
.btn-row--center   { max-width: 520px; margin-inline: auto }
.btn--full         { width: 100% }               /* two-door cards, calculator CTA */
.form-mount        { margin-top: 1.4em }         /* callback section */
.footer-fine       { max-width: 70ch; margin-top: 1.4em }

/* The mockup set these colours inline on navy bands. */
.band-navy .lede,
.band-navy p           { color: #c3cfe2 }
.band-navy .fine       { color: #a9b8cf }

/* Calculator CTA: was style="width:100%" inside a JS string. */
.calc-cta              { margin-top: 1em }
.calc-cta .btn         { width: 100% }

/* Gravity Forms enqueues its own stylesheets while rendering the form, so they are
   always printed after the theme's. Every rule below is prefixed with `body` to win
   on specificity rather than with !important. */

/* ---------- 2. Gravity Forms bridge ---------------------------------------
   The design's form rules are written for plain `form .field` markup. Gravity
   Forms emits .gfield / .gfield_label / .ginput_container instead, so the same
   look is mapped onto its markup here rather than by restyling the design. */

body .gform_wrapper.gravity-theme .gform_fields      { display: block }
body .gform_wrapper.gravity-theme .gfield            { margin-bottom: 16px; padding: 0 }
body .gform_wrapper.gravity-theme .gfield_label,
body .gform_wrapper.gravity-theme legend.gfield_label {
  display: block;
  font: 700 .8rem/1.4 var(--sans);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: .4em;
  padding: 0;
}
/* Typed controls only. A bare `input` here also matched radios and checkboxes and
   drew them as 52px-tall, full-width, 2px-bordered boxes — the giant circles the
   client reported. dui.css line 274 does the same from `form input`, which is why
   the reset below is needed as well. */
body .gform_wrapper.gravity-theme .ginput_container input[type="text"],
body .gform_wrapper.gravity-theme .ginput_container input[type="tel"],
body .gform_wrapper.gravity-theme .ginput_container input[type="email"],
body .gform_wrapper.gravity-theme .ginput_container input[type="url"],
body .gform_wrapper.gravity-theme .ginput_container input[type="number"],
body .gform_wrapper.gravity-theme .ginput_container input[type="date"],
body .gform_wrapper.gravity-theme .ginput_container select,
body .gform_wrapper.gravity-theme .ginput_container textarea {
  width: 100%;
  min-height: 52px;
  padding: 12px 14px;
  font: 400 1rem/1.4 var(--sans);
  border: 2px solid var(--line);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--ink);
}
body .gform_wrapper.gravity-theme .ginput_container textarea { min-height: 100px; resize: vertical }

/* GF wraps choice fields in a fieldset; strip the browser default chrome. */
body .gform_wrapper.gravity-theme fieldset { border: 0; margin: 0; padding: 0; min-width: 0 }

/* ---------- choice fields (radio / checkbox) ------------------------------
   The approved DUI form was all typed controls, so the ported bridge never
   needed these. The form the page actually runs asks two radio questions, and
   without them dui.css's `form label { display:block; text-transform:uppercase }`
   turned every option into a full-width uppercase heading with the control
   stranded above it. */

body .gform_wrapper.gravity-theme .gfield_radio,
body .gform_wrapper.gravity-theme .gfield_checkbox { display: grid; gap: 2px }

body .gform_wrapper.gravity-theme .gchoice { display: flex; gap: 10px; align-items: flex-start; margin: 0 }

/* Undoes the block/uppercase field-label styling for the option's own text. */
body .gform_wrapper.gravity-theme .gchoice label {
  display: flex;
  align-items: flex-start;
  margin: 0;
  padding: 6px 0;
  /* the 17px control is too small to hit, so the label carries the tap target */
  min-height: 44px;
  font: 400 .97rem/1.5 var(--sans);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
  cursor: pointer;
}

/* Back to a native control: dui.css sized it as a text box. */
body .gform_wrapper.gravity-theme .gfield-choice-input,
body .gform_wrapper.gravity-theme .gchoice input[type="radio"],
body .gform_wrapper.gravity-theme .gchoice input[type="checkbox"] {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  min-height: 0;
  margin: 11px 0 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  accent-color: var(--navy);
}

body .gform_wrapper.gravity-theme .gfield--radio-inline .gfield_radio { display: flex; flex-wrap: wrap; gap: 6px 22px }

body .gform_wrapper.gravity-theme .gform_footer { margin: 0; padding: 0 }
body .gform_wrapper.gravity-theme .gform_footer input[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 54px;
  padding: 14px 24px;
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--cta);
  color: #fff;
  font: 700 1.02rem/1.2 var(--sans);
  cursor: pointer;
  transition: background-color .16s ease, transform .16s ease;
}
body .gform_wrapper.gravity-theme .gform_footer input[type="submit"]:hover {
  background: var(--cta-hover);
  transform: translateY(-1px);
}

body .gform_wrapper.gravity-theme .gfield_required { color: var(--cta) }
body .gform_wrapper.gravity-theme .gfield_description { font-size: .85rem; color: var(--ink-soft) }
body .gform_wrapper.gravity-theme .validation_message {
  font-size: .88rem;
  color: var(--cta);
  background: none;
  border: 0;
  padding: .3em 0 0;
}
body .gform_wrapper.gravity-theme .gform_validation_errors {
  border: 2px solid var(--cta);
  border-radius: var(--radius-sm);
  background: #fff;
  box-shadow: none;
}
body .gform_wrapper.gravity-theme .gform_validation_errors h2 { color: var(--cta); font-size: 1rem }

/* The form sits inside the design's .card, which already supplies the padding. */
body .card > .gform_wrapper.gravity-theme { margin: 0 }
body .card > .gform_wrapper.gravity-theme form { margin: 0 }

/* ---------- 3. WordPress chrome ------------------------------------------- */

/* wp_get_attachment_image() prints a height attribute; its presentational hint
   otherwise beats the design's aspect-ratio rules and stretches photographs. */
img { height: auto }
.media img { height: 100% }

/* The admin bar overlaps the utility bar for logged-in editors. */
body.admin-bar .sticky { bottom: 0 }

@media screen and (max-width: 782px) {
  body.admin-bar .sticky { bottom: 0 }
}

/* ============================================================================
   4. Design pass
   Refinements agreed after the conversion was rendered. Kept here rather than in
   home.css so the mockup stylesheet stays re-syncable.
   ========================================================================= */

/* ---------- footer, centred ------------------------------------------------ */

footer .wrap { text-align: center }

footer h2 {
  margin-bottom: .65em;
  letter-spacing: -.01em;
}

footer p {
  max-width: 62ch;
  margin-inline: auto;
}

/* The address is the only footer link that runs long; keep the underline quiet. */
footer a {
  text-decoration-color: rgba(255, 255, 255, .38);
  text-underline-offset: 3px;
}

footer a:hover { text-decoration-color: #fff }

/* Separate the disclaimer from the contact block instead of letting it run on. */
.footer-fine {
  max-width: 74ch;
  margin: 1.9em auto 0;
  padding-top: 1.5em;
  border-top: 1px solid var(--line-dark);
}

/* Below the footer sits the 76px of body padding that clears the sticky bar. With
   the paper background it read as a cream strip under a navy footer. */
@media (max-width: 979px) {
  body { background: var(--navy-3) }
}

/* ---------- header bar ----------------------------------------------------- */

/* Once the bar wraps to three rows on a phone, centre it rather than leaving the
   rating and the button on opposite edges. */
@media (max-width: 720px) {
  .util .wrap { justify-content: center }
  .util .acts { flex-wrap: wrap; justify-content: center }
}

/* ---------- credential seals ----------------------------------------------- */

/* The badges are five different aspect ratios. A shared minimum width turns a
   ragged row into an even rhythm without stretching any of the artwork. */
.trust .seal {
  min-width: 164px;
  justify-content: center;
}

@media (max-width: 560px) {
  .trust .seal { min-width: 108px }
}

/* ---------- Gravity Forms: alignment and gaps ------------------------------ */

/* The date field shipped at its own narrow width while every other control was
   full width, which broke the left-to-right rhythm of the card. */
body .gform_wrapper.gravity-theme .ginput_container_date input,
body .gform_wrapper.gravity-theme .gfield--type-date input[type="text"] {
  width: 100%;
}

body .gform_wrapper.gravity-theme .ginput_container_date { display: block }

/* GF sizes the textarea by rows; the design sizes it by height. */
body .gform_wrapper.gravity-theme .ginput_container textarea {
  height: 120px;
  min-height: 120px;
}

/* One consistent gap between fields, and no double gap before the button. */
body .gform_wrapper.gravity-theme .gfield { margin-bottom: 18px }

body .gform_wrapper.gravity-theme .gform_footer {
  margin: 0;
  padding: 0;
}

/* The fine print belongs with the button, not floating as another field. */
body .gform_wrapper.gravity-theme .ikd-form-fine { margin-bottom: 14px }
body .gform_wrapper.gravity-theme .ikd-form-fine p { margin: 0 }

/* Rendered by the section rather than as a field, the fine print closes the card
   under the send button — where the approved design puts it. */
.card > .fine.ikd-form-fine { margin: .9em 0 0 }

/* GF 2.9 renders a <button>, not the <input> the rules above were written for.
   It is given .btn .btn-cta .btn--full in dui/forms.php so it inherits the
   design's own button; this only closes the gap GF's reset leaves behind. */
body .gform_wrapper.gravity-theme .gform_footer .gform_button { width: 100% }

/* GF's own required asterisk sits tight against the label text. */
body .gform_wrapper.gravity-theme .gfield_required { margin-left: .25em }

/* Description text under a field, aligned with the input above it. */
body .gform_wrapper.gravity-theme .gfield_description { padding: .45em 0 0 }

/* The field list is a <ul>. If Gravity Forms ever loads its legacy bundle, the
   browser's default list padding insets every input from its own label. */
body .gform_wrapper .gform_fields {
  padding-left: 0;
  margin-left: 0;
  list-style: none;
}

body .gform_wrapper .gfield { list-style: none }

/* The brand lockup is a link home; the global `a { color: var(--link) }` would
   otherwise turn it maroon and underline it. */
.util .brand,
.util .brand:hover {
  color: var(--header-accent);
  text-decoration: none;
}

.util .brand:hover span { color: var(--header-ink) }

.util .brand:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
  border-radius: 6px;
}

/* ---------- sticky header -------------------------------------------------- */

.util {
  position: sticky;
  top: 0;
  /* Above page content, below the mobile call bar (z-index 70) is not enough —
     the bar must also clear the hero's decorative glow. */
  z-index: 80;
}

/* The admin bar is fixed for logged-in editors on desktop, and scrolls away
   below 782px, so the offset only applies on the wider screens. */
body.admin-bar .util { top: var(--wp-admin--admin-bar--height, 32px) }

@media screen and (max-width: 782px) {
  body.admin-bar .util { top: 0 }
}

/* Lift the bar off the page once it is actually stuck — see home.js. */
.util.is-stuck { box-shadow: 0 6px 18px rgba(18, 35, 63, .14) }

/* The bar's type was set for a dark strip of fine print. On the light bar it is the firm's
   phone number and rating, so it carries the weight of real content — the CTA is sized up
   with it, otherwise the button reads as smaller than the number sitting next to it. */
.util .acts .btn {
  font-size: 1.02rem;
  padding: 11px 22px;
  min-height: 46px;
}

/* No scroll-margin here on purpose. The bar is 62px on desktop but wraps to two
   rows at some widths, so any fixed offset is wrong somewhere — a 84px guess left
   the calculator 12px under the bar at 768px. home.js measures the bar instead. */

/* Below desktop the bar wraps and a sticky bar that tall eats the screen. The
   rating is the decorative part — the phone number and the deadline button are
   what the bar is for — so it goes at the same 980px breakpoint the rest of the
   design already switches on. */
@media (max-width: 979px) {
  .util .rating { display: none }
}

/* ---------- thank-you and not-found screens -------------------------------- */

/* One band filling the screen, so these do not read as a truncated page. */
.status-band {
  display: flex;
  align-items: center;
  min-height: 64vh;
}

.status-band h1 {
  margin-bottom: .45em;
  color: #fff;
  font-size: clamp(1.9rem, 4.4vw, 3rem);
}

/* ---------- sticky short column -------------------------------------------
   Where a two-column section has much less on one side, that side follows the
   scroll instead of leaving a long blank gap. Measured on this content:
   banner 822 vs 388px, "the first 72 hours" 654 vs 330px. The law-explained and
   penalties columns are within ~60px of each other, so the same rules simply
   never engage there — sticky does nothing when a column fills its row.

   Applied by role, never by section: the picture and the calculator card are the
   supporting side, so this stays correct if the copy changes.
   ------------------------------------------------------------------------- */

@media (min-width: 980px) {
  .hero-grid > div:last-child,
  .split .portrait {
    position: sticky;
    /* clears the sticky header, plus breathing room */
    top: 86px;
    /* Grid items stretch by default; a stretched item fills the row and has
       nowhere to travel. Starting it lets it move inside its grid area. */
    align-self: start;
  }

  /* The banner clips its decorative glow with overflow:hidden, which makes it a
     scroll container — nothing inside it can then stick. `overflow: clip` clips
     exactly the same box without creating one. clip-path was tried first and is
     wrong here: it clips painting only, so the glow still widened the document
     and brought back horizontal scrolling. */
  .hero { overflow: clip }
}

/* Below 980px every one of these sections is a single column, so nothing is
   sticky — the picture sits in the reading order where it belongs. */
@media (max-width: 979px) {
  .hero-grid > div:last-child,
  .split .portrait {
    position: static;
  }
}

/* WordPress' own class, which this theme never needed until the footer heading
   had to stay in the document for structure without being drawn twice. Lifted
   from core so it behaves exactly as editors and plugins expect. */
.screen-reader-text {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.screen-reader-text:focus {
  position: static !important;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip-path: none;
  white-space: normal;
}

/* ---------- the firm lockup (header + footer) ------------------------------ */

.ikd-lockup { display: inline-flex; align-items: center }

/* The text fallback keeps the mockup's original wordmark exactly. */
.ikd-lockup--text { gap: 9px }

.ikd-lockup__img {
  display: block;
  width: auto;
  height: 78px;
}

.ikd-lockup--footer .ikd-lockup__img { height: 44px }

/* The bar wraps to two rows below 980px and a 70px logo on a sticky bar eats the
   screen, so the lockup steps down with the layout. */
@media (max-width: 979px) {
  .util .ikd-lockup__img { height: 58px }
}

@media (max-width: 480px) {
  .util .ikd-lockup__img { height: 44px }
}

/* The footer bar is still dark navy and the artwork is dark navy on transparency,
   so down there the logo needs a light panel to read at all. The header bar is
   light (--header-bg), so the logo sits on it directly — no panel, no white box.
   ikd_lockup() only ever adds this class in the footer. */
.ikd-lockup--plate {
  padding: 10px 16px;
  border-radius: 8px;
  background: #fff;
}

/* Same treatment the wordmark's locality line had in the mockup. */
.ikd-lockup__where {
  font: 600 .66rem/1.3 var(--sans);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: #93a4c0;
}

@media (max-width: 480px) {
  .ikd-lockup__where { display: none }
}

.footer-logo {
  display: inline-block;
  margin-bottom: 1.1em;
  text-decoration: none;
}

.footer-logo:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
  border-radius: 10px;
}

/* The header lockup has its own step-down above; this is the footer's. */
@media (max-width: 720px) {
  .ikd-lockup--footer .ikd-lockup__img { height: 38px }
}

/* ---------- credential seals: larger, and moving --------------------------- */

.trust { overflow: hidden }

/* The track holds two identical runs of seals; the animation travels exactly
   one run, so the loop is seamless. home.js builds the second run. */
.trust-track {
  display: flex;
  align-items: center;
  gap: 14px 26px;
  width: max-content;
}

.trust-track--animated {
  animation: ikd-seal-marquee 34s linear infinite;
}

.trust:hover .trust-track--animated,
.trust:focus-within .trust-track--animated {
  animation-play-state: paused;
}

@keyframes ikd-seal-marquee {
  from { transform: translateX(0) }
  /* Half the track is one full run of seals, gap included. */
  to   { transform: translateX(calc(-50% - 13px)) }
}

.trust .seal { flex: 0 0 auto }

/* Larger again at the client's request — the mockup ran these at 52px. */
.trust img { height: 84px }

@media (max-width: 900px) {
  .trust img { height: 72px }
  .trust .seal { min-width: 132px }
}

@media (max-width: 560px) {
  .trust img { height: 60px }
  .trust .seal { min-width: 104px }
}

/* Until the second run exists the row must still centre, and a visitor who has
   asked for less motion never gets the marquee. */
@media (prefers-reduced-motion: reduce) {
  .trust-track--animated { animation: none }
  .trust-track { flex-wrap: wrap; justify-content: center; width: 100% }
}

/* ---------- the "first 72 hours" photograph fills its side ----------------- */

/* The picture fills its whole side of the section. It is taken out of flow so it
   can only ever match the text column: with `height:100%` in normal flow the
   image's own aspect ratio wins whenever it is the taller item, which grew the
   law-explained section by 211px the first time this was tried. */
@media (min-width: 980px) {
  .media figure {
    position: relative;
    /* No offset: `top` on a relative box shifts it, which is what pushed the
       picture 86px down and out of its section. */
    top: auto;
    align-self: stretch;
    min-height: 260px;
  }

  .media figure img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* home.css caps this at 520px; the picture is meant to fill the column now. */
    max-height: none;
    object-fit: cover;
    object-position: center;
  }
}

/* Stacked, the picture is back in the reading order at its natural shape — an
   absolutely positioned image in a single column would collapse to nothing. */
@media (max-width: 979px) {
  .media figure img {
    width: 100%;
    height: auto;
    max-height: none;
    object-fit: cover;
  }
}

/* ---------- back to top ---------------------------------------------------- */

.to-top {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 75;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 2px solid rgba(255, 255, 255, .22);
  border-radius: 50%;
  background: var(--navy-3);
  color: #fff;
  cursor: pointer;
  /* Out of the way until the page has been scrolled, and never a tab stop while
     it is hidden. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity .2s ease, transform .2s ease, visibility .2s, background-color .16s ease;
}

.to-top.is-visible {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.to-top:hover {
  background: var(--cta);
  border-color: var(--cta);
}

.to-top:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
}

.to-top svg { width: 20px; height: 20px }

/* The mobile call/text bar owns the bottom of the screen below 980px, so the
   arrow sits above it rather than on top of it. */
@media (max-width: 979px) {
  .to-top {
    right: 14px;
    bottom: 82px;
    width: 44px;
    height: 44px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .to-top { transition: opacity .2s ease, visibility .2s }
}

/* ---------- header phone: a button on mobile ------------------------------- */

/* On a phone the number sits directly beside the solid CTA, and a bare text link
   next to a solid pill reads as unfinished. It becomes an outlined pill with the
   same geometry as .btn-sm, so the pair look like one set. It is outlined rather
   than filled white because the bar itself is light now — a white pill on
   --header-bg has almost no edge. */
@media (max-width: 720px) {
  .util .tel {
    min-height: 44px;
    padding: 10px 18px;
    border: 2px solid var(--header-accent);
    border-radius: var(--radius-sm);
    background: #fff;
    color: var(--header-accent);
    font: 700 .94rem/1.2 var(--sans);
    justify-content: center;
    transition: background-color .16s ease, transform .16s ease;
  }

  .util .tel:hover {
    background: #fff3e6;
    text-decoration: none;
    transform: translateY(-1px);
  }

  .util .tel:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: 3px;
  }

  .util .acts {
    gap: 10px;
    width: 100%;
    justify-content: center;
    flex-wrap: wrap;
  }

  /* Each pill sizes to its own label. Forcing them to equal widths made the CTA
     wrap onto two lines, so the pair no longer matched in height — the very thing
     this was meant to fix. They wrap as whole pills on a very narrow screen. */
  .util .acts .tel,
  .util .acts .btn {
    flex: 0 1 auto;
    white-space: nowrap;
  }
}
