/* ==========================================================================
   OOGLE - WORDPRESS ADJUSTMENT LAYER

   Loaded last, after tokens, styles and art. Its only job is the seam: the
   places where GeneratePress' structure, the block editor's output and
   Gravity Forms' controls meet a design system that was written for markup
   Oogle authored completely.

   Rules for this file:
   1. Nothing here re-states a design decision. Every value is a token from
      tokens.css. A hard-coded colour or size in this file is a bug.
   2. No !important is added to win a specificity argument. Oogle's sheets
      load after GeneratePress, so source order settles equal-specificity ties
      on its own.
   3. Every block says what it is settling and why, because in six months the
      reason is the only thing that makes it safe to delete.

   The first two blocks are not adjustments. They are the measure ladder and
   the V5.21 type sizes, which used to be two files of their own (measures.css,
   type-v521.css: 1.8 KB and 1.2 KB, two render-blocking requests on every
   page for three kilobytes). They sit here at the top because their place in
   the cascade is exactly here: after art.css and lp.css, before anything in
   this file, which is the order the two files loaded in.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0a. THE MEASURE LADDER (was measures.css)
   MEASURE UTILITIES

   The named measure ladder. V5.20 replaced 180 inline style="max-width:NNch"
   attributes across 51 pages with these 15 classes, and its own note says why
   in terms that matter here: GenerateBlocks has no per-block max-width in ch,
   so every one of those declarations would otherwise have become a hand-added
   inline style in the block editor, which a client eventually deletes, or a
   bespoke class invented one at a time.

   In the static build these rules were GENERATED by build.py at bundle time
   from the ch values the source used, so they existed only in the shipped
   stylesheet and in none of the source files. Porting the source alone left
   all 15 of them undefined: every .mw-*ch class on every page was inert, and
   the first symptom was the /website-repair/ heading rendering on one line
   instead of two because its 16ch cap did nothing. The visual comparison
   against V5.22 measured it as a 62px section-height difference; nothing on
   the page looked broken.

   The ladder is now authored rather than generated, because in WordPress an
   editor picks a measure from a list rather than a build step inferring one.
   Adding a value is one line here.
   -------------------------------------------------------------------------- */

.mw-11ch { max-width: 11ch; }
.mw-12ch { max-width: 12ch; }
.mw-13ch { max-width: 13ch; }
.mw-14ch { max-width: 14ch; }
.mw-15ch { max-width: 15ch; }
.mw-16ch { max-width: 16ch; }
.mw-22ch { max-width: 22ch; }
.mw-24ch { max-width: 24ch; }
.mw-26ch { max-width: 26ch; }
.mw-34ch { max-width: 34ch; }
.mw-36ch { max-width: 36ch; }
.mw-44ch { max-width: 44ch; }
.mw-46ch { max-width: 46ch; }
.mw-52ch { max-width: 52ch; }
.mw-56ch { max-width: 56ch; }

/* --------------------------------------------------------------------------
   0b. V5.21 TYPE SIZES (was type-v521.css)
   V5.21 typography, restored.
  
   V5.21 is the typography source of truth for this build. Measured in a
   browser against changelogs.com/oogle521 at the same viewport, V5.22 and
   V5.21 already agree on every face, size, weight, line height, letter
   spacing and transform, with three exceptions: V5.22 added viewport and
   container clamps to the two display sizes.
  
       h1, .display     min(var(--t-display), 11vw)
       h2, .h2          min(var(--t-h2), 9vw)
       .phero-copy h1   min(var(--t-display), 12.5cqi)
  
   Those clamps only bite below roughly 370px, where they render every h2 at
   27-28.8px instead of V5.21's 30px, and they shrink an internal page's h1
   against its column rather than the viewport. This file puts the V5.21
   values back. Nothing else about the type system needed changing, because
   nothing else differed.
  
   If a heading overflows at 320px without the clamp, that is a V5.21
   typography question to answer deliberately. It is not a reason to quietly
   reinstate a size the approved build does not use.
   -------------------------------------------------------------------------- */

h1,
.display {
  font-size: var(--t-display);
}

h2,
.h2 {
  font-size: var(--t-h2);
}

.phero-copy h1 {
  font-size: var(--t-display);
}

/* --------------------------------------------------------------------------
   1. GENERATEPRESS STRUCTURE

   GeneratePress centres and pads .site-content for a conventional document.
   Oogle's sections are full-bleed and centre themselves with .wrap, so the
   outer container has to stop constraining them. .wrap is untouched and still
   owns the measure.
   -------------------------------------------------------------------------- */
.oogle-page .site-content,
.oogle-page .content-area,
.oogle-page .site-main,
.oogle-page .inside-article {
  max-width: none;
  margin: 0;
  padding: 0;
}

/* #page carries GeneratePress' container width, 1200px by default. That is
   the outer boundary, and it was the one that mattered: with it in place the
   design system's own measure could never reach its 1280px, so every panel on
   every page rendered 1085px wide instead of 1280, and the service hero's
   headline came out at 58.9px instead of 66.5px because .phero-copy is
   container-type: inline-size and its h1 is capped at 12.5cqi. One container
   nobody could see was resizing the type.

   .wrap is the single measure for this design system and it is the only thing
   that should own the page's width. Doing this in CSS rather than in the
   Customizer keeps it out of reach of a settings change. */
.oogle-page #page,
.oogle-page > .site.grid-container {
  max-width: none;
  margin: 0;
  padding: 0;
  width: auto;
}

.oogle-page .site-content { display: block; }
.oogle-page .separate-containers .site-main { margin: 0; }

/* --------------------------------------------------------------------------
   2. EDITOR CONTENT

   The content area carries .prose, which is the design system's own editorial
   treatment: the dash marker on unordered lists, the tabular counter on
   ordered ones, underlined links, the heading rhythm. That is what stops the
   global element reset in styles.css stripping bullets and margins out of
   block content, and it does it with the site's own design rather than by
   restoring browser defaults.

   What is left is the handful of block classes .prose has never met.
   -------------------------------------------------------------------------- */
.prose > .wp-block-image { margin-top: var(--s7); }
.prose .wp-block-image img { border-radius: var(--radius-inset); }
.prose figcaption { margin-top: var(--s3); font-size: var(--t-sm); color: var(--text-faint); }
.prose .wp-block-quote { padding-left: var(--s5); border-left: 2px solid var(--mark); }
.prose .wp-block-separator { margin-block: var(--s9); border-top: 1px solid var(--line); }
.prose .wp-block-table { display: block; overflow-x: auto; }
/* Inside the article's own scrolling region (blocks-resources.php, which is
   focusable and labelled) the figure must not scroll on its own, or there
   are two scrollable regions and the inner one has no keyboard access. */
.art-table .wp-block-table { overflow: visible; }
.prose .wp-block-table td,
.prose .wp-block-table th { border: 1px solid var(--line); padding: var(--s3) var(--s4); }

/* A core group block inside .prose puts its children in an inner container,
   which makes them grandchildren and stops `.prose > * + *` matching. Oogle's
   own prose block renders one element and does not have this problem; this
   rule is here so a group dropped in by hand still reads correctly. */
.prose > .wp-block-group__inner-container > * + * { margin-top: var(--s5); }
.prose > .wp-block-group__inner-container > h3 { margin-top: var(--s9); }
.prose > .wp-block-group__inner-container > h3:first-child { margin-top: 0; }

/* A wide or full-aligned block inside .wrap has nothing to be wide against.
   Give it the gutter back rather than let it push the page sideways. */
.prose .alignwide,
.prose .alignfull { max-width: 100%; margin-inline: 0; }

/* --------------------------------------------------------------------------
   3. GRAVITY FORMS

   styles.css resets button and list at element level, which is right for
   Oogle markup and wrong for a plugin that ships its own controls. These
   rules hand Gravity Forms back what the reset took, in Oogle's design rather
   than the plugin's: the same border, radius, padding, focus ring and error
   colour that .f already uses on the static build's intake forms.
   -------------------------------------------------------------------------- */
.gform_wrapper ul,
.gform_wrapper ol { padding: 0; list-style: none; }

.gform_wrapper .gform_fields { display: grid; gap: var(--s5); }

.gform_wrapper .gfield_label {
  display: block;
  margin-bottom: 7px;
  font-size: var(--t-sm);
  font-weight: var(--w-semi);
  color: var(--ink-2);
}

.gform_wrapper .gfield_required { color: var(--fault); }
.gform_wrapper .gfield_description { font-size: var(--t-xs); color: var(--ink-4); }

/* Cloudflare Turnstile (the add-on's field). The widget is drawn by
   Cloudflare's script after the page paints; the flexible size is 65px
   tall, so the box is reserved and nothing below it moves. */
.gform_wrapper .ginput_container_turnstile { min-height: 65px; }
.gform_wrapper .cf-turnstile iframe { display: block; }
/* The line above the fields ("Every field is required unless it says
   optional.") sits outside the Gravity Forms wrapper, where V5.22's .f .hint
   rule cannot reach it. Same type, same colour, same gap as V5.22 gave it. */
.intake-body > .hint,
.lp-form > .hint { font-size: var(--t-xs); color: var(--ink-4); margin: 0 0 var(--s5); }

.gform_wrapper input[type="text"],
.gform_wrapper input[type="email"],
.gform_wrapper input[type="tel"],
.gform_wrapper input[type="url"],
.gform_wrapper input[type="number"],
.gform_wrapper select,
.gform_wrapper textarea {
  width: 100%;
  min-width: 0;
  padding: 12px 15px;
  border: 1px solid var(--control-edge);
  border-radius: var(--radius-input);
  background: var(--paper);
  color: var(--ink);
  font-size: var(--t-body);
  transition: border-color var(--d-state) var(--ease), box-shadow var(--d-state) var(--ease);
}

/* V5.22 sizes this box with min-height and no rows attribute. Gravity Forms
   writes rows="10", and the intrinsic height of ten rows beats a min-height,
   so the description box rendered about twice as tall as the approved design.
   An explicit height makes the rows attribute irrelevant without editing GF's
   markup, and resize keeps it draggable. */
.gform_wrapper.gform-theme .gform_fields .gfield textarea { min-height: var(--gf-ctrl-textarea-height, 132px); height: var(--gf-ctrl-textarea-height, 132px); resize: vertical; line-height: 1.55; }

.gform_wrapper input:focus,
.gform_wrapper select:focus,
.gform_wrapper textarea:focus {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px var(--blue-film-2);
}

/* V5.14's rule, and the reason for it: a brand glow measures 1.21:1 against
   the page and is not a focus indicator. The glow stays, the ring comes back
   on top of it. */
.gform_wrapper input:focus-visible,
.gform_wrapper select:focus-visible,
.gform_wrapper textarea:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.gform_wrapper .gfield_error input,
.gform_wrapper .gfield_error select,
.gform_wrapper .gfield_error textarea { border-color: var(--fault); }

.gform_wrapper .validation_message,
.gform_wrapper .gform_validation_errors { color: var(--fault); font-size: var(--t-xs); }

/* Gravity Forms 3 ships the Orbital theme, which sets every control property
   through its own custom properties and wins on specificity over the rules
   above. Overriding the rules one by one was a losing race; setting the
   properties is the mechanism the theme offers, and it holds whatever order
   the sheets load in. Values are V5.22's .f rules. */
.gform_wrapper.gform-theme.gform-theme--foundation.gform-theme--framework {
  /* Orbital's per-form block names sizes by step (inputSize lg, set by
     oogle_gf_default_styles); these are what the steps measure. */
  --gf-ctrl-size-lg: 46px;
  --gf-ctrl-btn-size-lg: 54px;
  --gf-ctrl-btn-padding-x-lg: 30px;
  --gf-ctrl-btn-font-size-lg: var(--t-body);
  --gf-ctrl-radius: var(--radius-input);
  --gf-ctrl-padding-x: 15px;
  --gf-ctrl-font-size: var(--t-body);
  --gf-ctrl-bg-color: var(--paper);
  --gf-ctrl-border-color: var(--control-edge);
  --gf-ctrl-border-color-hover: var(--control-edge);
  --gf-ctrl-border-color-focus: var(--blue);
  --gf-ctrl-border-color-error: var(--fault);
  --gf-ctrl-placeholder-color: var(--ink-5);
  --gf-ctrl-placeholder-opacity: 1;
  --gf-ctrl-textarea-height: 132px;
  --gf-ctrl-textarea-padding-y: 12px;
  --gf-ctrl-label-font-size-primary: var(--t-sm);
  --gf-ctrl-label-font-weight-primary: var(--w-semi);
  --gf-ctrl-label-color-primary: var(--ink-2);
  --gf-label-space-primary: 7px;
  --gf-ctrl-desc-font-size: var(--t-xs);
  --gf-ctrl-desc-color: var(--ink-4);
  --gf-desc-space: 7px;
  --gf-field-gap-x: var(--s5);
  --gf-field-gap-y: var(--s5);
  --gf-form-gap-y: var(--s5);
  --gf-ctrl-btn-radius: var(--radius-pill);
  --gf-ctrl-btn-font-weight: var(--w-bold);
  --gf-ctrl-btn-bg-color-primary: var(--blue);
  --gf-ctrl-btn-bg-color-hover-primary: var(--blue-deep);
  --gf-ctrl-btn-bg-color-focus-primary: var(--blue-deep);
  --gf-ctrl-btn-border-color-primary: transparent;
  --gf-ctrl-btn-border-color-hover-primary: transparent;
}

/* A correction to V5.22, not a WordPress adjustment. The plan echo above the
   intake form is written with the hidden attribute and shown by main.js only
   when ?problem= names a plan. styles.css gives .plan-echo display:flex, which
   outranks the user-agent's [hidden] rule, so the approved build shows an
   empty "You're asking about" box to every visitor who arrives without a
   plan. The attribute's intent is not in doubt; this makes it hold. */
.plan-echo[hidden] { display: none; }

/* The hint above the fields already says every field is required unless it
   says optional. The forms use an empty custom indicator; this catches any
   theme that prints one anyway. */
.gform_wrapper .gfield_required { display: none; }

/* The row under the fields: V5.22's button and its paragraph side by side
   under a rule (.form-foot) or stacked with a full-width button (.lp-form-foot).
   The paragraph is placed inside the Gravity Forms footer by oogle_gf_foot(),
   so the footer itself adds nothing. */
/* Gravity Forms' reset matches every descendant of the wrapper at class
   weight, which ties V5.22's .form-foot and wins on order. Restated at two
   classes, values from styles.css and lp.css. */
.gform_wrapper.gform-theme .gform_footer { display: block; margin: 0; padding: 0; }
.gform_wrapper .form-foot {
  display: flex; flex-wrap: wrap; gap: var(--s5); align-items: center;
  margin-top: var(--s7); padding-top: var(--s6); border-top: 1px solid var(--line);
}
.gform_wrapper .form-foot p { margin: 0; font-size: var(--t-xs); color: var(--ink-4); max-width: 44ch; }
.gform_wrapper .form-foot .gform_button { flex: none; }
.gform_wrapper .lp-form-foot { margin-top: var(--s7); }
.gform_wrapper .lp-form-foot p { margin-top: var(--s5); font-size: var(--t-sm); color: var(--text-dim); line-height: 1.55; }
.lp-form .gform_wrapper.gform-theme .gform_footer .lp-form-foot .gform_button { display: flex; width: 100%; inline-size: 100%; }
.gform_wrapper .gform_required_legend { display: none; }
.lp-form .gform_wrapper.gform-theme.gform-theme--foundation.gform-theme--framework {
  --gf-ctrl-textarea-height: 88px;
}

/* The submit control is a <button> on Gravity Forms 3, and the element reset
   flattened it to bare text. Both shapes get the Oogle button. */
.gform_wrapper .gform_button,
.gform_wrapper button[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s3);
  padding: 17px 30px;
  min-height: 54px;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: var(--blue);
  color: #fff;
  font-size: var(--t-body);
  font-weight: var(--w-bold);
  line-height: 1;
  cursor: pointer;
  transition: background var(--d-tap) var(--ease);
}

.gform_wrapper .gform_button:hover,
.gform_wrapper button[type="submit"]:hover { background: var(--blue-deep); }

/* Radio and checkbox groups, as the pill controls the intake forms use. The
   border is the control boundary, which is what satisfies 1.4.11.

   V5.22 puts the input INSIDE the label and hides it, so the pill is the
   label. Gravity Forms puts the input beside the label inside a .gchoice
   wrapper, so styling the label alone left a native radio circle sitting
   outside a pill: two controls where the design has one. The pill is the
   .gchoice here, and the input is hidden the same way V5.22 hides it, which
   keeps it focusable and keeps the label association intact. */
/* Specificity note: Gravity Forms' own theme sheet sets flex-direction:column
   on the group and display:grid on each choice, and it is more specific than
   a two-class selector, so the pills stacked full width. These selectors match
   its weight rather than reaching for !important. */
.gform_wrapper.gform-theme .gform_fields .gfield_radio,
.gform_wrapper.gform-theme .gform_fields .gfield_checkbox {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--s2);
}

.gform_wrapper.gform-theme .gform_fields .gfield_radio .gchoice,
.gform_wrapper.gform-theme .gform_fields .gfield_checkbox .gchoice {
  width: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border: 1px solid var(--control-edge);
  border-radius: var(--radius-pill);
  background: var(--paper);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--d-tap) var(--ease), background var(--d-tap) var(--ease), color var(--d-tap) var(--ease);
}

.gform_wrapper.gform-theme .gform_fields .gfield_radio .gchoice input,
.gform_wrapper.gform-theme .gform_fields .gfield_checkbox .gchoice input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
}

.gform_wrapper.gform-theme .gform_fields .gfield_radio .gchoice label,
.gform_wrapper.gform-theme .gform_fields .gfield_checkbox .gchoice label {
  margin: 0;
  cursor: pointer;
  font-size: var(--t-sm);
  font-weight: var(--w-mid);
  color: inherit;
}

.gform_wrapper.gform-theme .gform_fields .gfield_radio .gchoice:hover,
.gform_wrapper.gform-theme .gform_fields .gfield_checkbox .gchoice:hover { border-color: var(--line-2); background: var(--paper-2); }

.gform_wrapper.gform-theme .gform_fields .gfield_radio .gchoice:has(input:checked),
.gform_wrapper.gform-theme .gform_fields .gfield_checkbox .gchoice:has(input:checked) {
  border-color: var(--blue);
  background: var(--blue-film);
  color: var(--blue);
}

.gform_wrapper.gform-theme .gform_fields .gfield_radio .gchoice:has(input:focus-visible),
.gform_wrapper.gform-theme .gform_fields .gfield_checkbox .gchoice:has(input:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   4. ADMIN BAR

   The header is sticky and the admin bar is fixed chrome above it. Without
   this the two overlap for every logged-in editor.
   -------------------------------------------------------------------------- */
.admin-bar .hdr,
.admin-bar .mnav { top: 32px; }

@media screen and (max-width: 782px) {
  .admin-bar .hdr,
  .admin-bar .mnav { top: 46px; }
}

/* --------------------------------------------------------------------------
   5. THE DARK CALL TO ACTION

   V5.22 wrote these two as inline style attributes on /get-help/ and
   /start-a-project/. Inline styles are the reason the Content-Security-Policy
   carries style-src 'unsafe-inline', and a block cannot carry one anyway
   without handing an editor a style attribute to break. Two named rules.
   -------------------------------------------------------------------------- */
.dark-cta-grid { gap: var(--s7) var(--s8); align-items: center; }
.dark-cta-act { justify-content: flex-end; }

@media (max-width: 900px) {
  .dark-cta-act { justify-content: flex-start; }
}

/* A framed standing image. V5.22 wrote the frame and the fit as inline styles
   on the element; a block cannot carry those without handing an editor a style
   attribute to break, so they are a class. */
.oogle-figure { padding: 0; overflow: hidden; }
.oogle-figure-img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

/* --------------------------------------------------------------------------
   6. MIGRATION SCAFFOLDING

   A contextual link whose destination has not been migrated yet renders as its
   own text rather than as a dead link. It should read as ordinary prose, not
   as a broken control, so it takes the surrounding colour and nothing else.
   On a fully migrated site nothing matches this rule.
   -------------------------------------------------------------------------- */
/* A destination that is not migrated yet renders as a span rather than an
   anchor, so nobody can click into a 404. It should read as "listed, not yet
   linked", not as a broken link, so where the component gives its links a
   visible box the span keeps the box and loses the colour. It deliberately
   does NOT look like a working link: the affordance has to be honest.

   All of this disappears on its own as each destination is migrated. */
.oogle-pending-link { color: inherit; text-decoration: none; }

.case-serv .oogle-pending-link {
  font-size: var(--t-xs);
  border: 1px dashed var(--rule);
  border-radius: var(--radius-pill);
  padding: 5px 11px;
  color: var(--text-faint);
}
