Buttons stop being indigo, and the hero gets its light back

23f6f22625a0 · AtlantisPleb · · parent 1f177cf5f533

Buttons stop being indigo, and the hero gets its light back

The primary button was the last saturated element on a monochrome surface.
Measured from the reference rather than guessed: its primary control is
`#e5e5e6` with `#08090a` text — the page's own background used as ink — and no
hue at all. `--control-inverse-bg` and `--control-inverse-fg` already resolve
to exactly that, so this is the token ladder finally applied where it was
meant to. Hover brightens toward white instead of shifting hue, the halo is
gone, and `:active` scales to .97, which the reference also does.

The hero's glow lived inside its figure block, so commenting the figure out
took the light with it and left the headline on flat ink. It belongs to the
words, and now sits under them.

"Built with Elixir / Phoenix / LiveView / PostgreSQL" is gone. The footer's
closing line becomes a bar with two edges: who owns this on the left, how it
is licensed on the right. Read as one centred line they ran together.

The account menu's name wrapped mid-name, because the panel sized itself to
its shortest row and "Christopher David" did not fit. The name sets the
panel's width now and truncates rather than wrapping past a ceiling; the
handle beneath it already identifies the account.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0149rBWy7br1Z7bbz9NrQhEr
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • modified assets/css/openagents.css
  • modified lib/openagents_web/components/landing.ex
  • modified lib/openagents_web/live/home_live.ex

Diff

3 files changed, +83 -17

assets/css/openagents.css modified +67 -7

@@ -619,10 +619,28 @@

619 619
620 620
  /* Variants */
621 621
  .btn:not([data-variant]),
622
  /* Inverted, not accented. Measured from the reference: its primary control
623
     is `#e5e5e6` with `#08090a` text -- the page's own background colour used
624
     as ink -- and no hue at all. `--control-inverse-bg` and
625
     `--control-inverse-fg` already resolve to that pair, so this is the token
626
     ladder finally being used where it was always meant to apply. The indigo
627
     fill was the last saturated element on a monochrome surface. */
628
  /* A press the finger can feel. Taken from the reference, which scales its
629
     buttons to .97 on :active. */
630
  .btn:active:not(:disabled) {
631
    transform: scale(0.97);
632
  }
633
634
  @media (prefers-reduced-motion: reduce) {
635
    .btn:active:not(:disabled) {
636
      transform: none;
637
    }
638
  }
639
622 640
  .btn[data-variant="primary"] {
623
    border-color: var(--accent);
624
    background: var(--accent);
625
    color: var(--text-primary);
641
    border-color: var(--control-inverse-bg);
642
    background: var(--control-inverse-bg);
643
    color: var(--control-inverse-fg);
626 644
  }
627 645
628 646
  /* Hover states are gated behind (hover: hover) throughout this pack: on

@@ -631,11 +649,13 @@

631 649
     visible at rest — so the fallback is simply the resting state, and
632 650
     :focus-visible and :active stay ungated. */
633 651
  @media (hover: hover) {
652
    /* Hover brightens toward white rather than shifting hue, which is what the
653
       reference does (`#e5e5e6` to `#fff`). No halo: a glow around a already
654
       high-contrast control reads as a focus ring that is not one. */
634 655
    .btn:is(:not([data-variant]), [data-variant="primary"]):hover:not(:disabled) {
635
      border-color: var(--accent-bright);
636
      background: var(--accent-bright);
637
      box-shadow: var(--halo);
638
      color: var(--ink-void);
656
      border-color: var(--text-ink);
657
      background: var(--text-ink);
658
      color: var(--control-inverse-fg);
639 659
    }
640 660
  }
641 661

@@ -1630,6 +1650,8 @@

1630 1650
   * and pins the menu open. Declare no `display` here so the user agent keeps
1631 1651
   * control of open and closed state. Position is app-shell layout. */
1632 1652
  .menu {
1653
    /* Sized by its widest row rather than by its narrowest. */
1654
    min-width: max-content;
1633 1655
    /* A native popover is centred by the user agent's `margin: auto`. Setting
1634 1656
       `margin: 0` defeated that and pinned every menu to the viewport's
1635 1657
       top-left corner -- the account menu included, not just this demo. Keep

@@ -1668,6 +1690,8 @@

1668 1690
    gap: 10px;
1669 1691
    border-bottom: 1px solid var(--line);
1670 1692
    padding: 12px;
1693
    /* Long names still have a ceiling: the menu is a menu, not a card. */
1694
    max-width: 20rem;
1671 1695
  }
1672 1696
1673 1697
  .menu__identity span {

@@ -1676,11 +1700,19 @@

1676 1700
    flex-direction: column;
1677 1701
  }
1678 1702
1703
  /* One line. The panel sizes to its content, and its other rows are short, so
1704
     a two-word name wrapped mid-name and made the identity look like two
1705
     fields. The name is what sets the panel's width now; an unusually long one
1706
     truncates rather than wrapping, since the handle beneath it already
1707
     identifies the account. */
1679 1708
  .menu__identity strong {
1709
    overflow: hidden;
1680 1710
    color: var(--text-primary);
1681 1711
    font-size: 0.8125rem;
1682 1712
    font-weight: 600;
1683 1713
    line-height: 1.25rem;
1714
    text-overflow: ellipsis;
1715
    white-space: nowrap;
1684 1716
  }
1685 1717
1686 1718
  .menu__identity small {

@@ -4859,3 +4891,31 @@

4859 4891
    font-variant-numeric: tabular-nums;
4860 4892
  }
4861 4893
}
4894
4895
@layer components {
4896
  /* The hero's own light, behind the words rather than behind a figure. Placed
4897
     under the lede and pushed back, so it lifts the headline without washing
4898
     it: the text sits above it at z-index 1 through `.landing-section__inner`. */
4899
  .hero__glow {
4900
    top: 38%;
4901
    z-index: 0;
4902
  }
4903
4904
  /* Two edges of one line. The copyright says who owns this and the note says
4905
     how it is licensed; centring them together reads as one run-on sentence. */
4906
  .landing-footer__bar {
4907
    display: flex;
4908
    flex-wrap: wrap;
4909
    align-items: baseline;
4910
    justify-content: space-between;
4911
    gap: 8px 24px;
4912
    max-width: 1104px;
4913
    margin-inline: auto;
4914
    padding-block-start: 32px;
4915
  }
4916
4917
  .landing-footer__bar .landing-footer__note {
4918
    padding-block-start: 0;
4919
    margin: 0;
4920
  }
4921
}
lib/openagents_web/components/landing.ex modified +14 -2

@@ -131,6 +131,11 @@ defmodule OpenAgentsWeb.UI.Landing do

131 131
  def hero(assigns) do
132 132
    ~H"""
133 133
    <.section class={["hero", @class]} rule={false}>
134
      <%!-- The lede's own light. This used to live inside the figure block, so
135
      commenting the figure out took the glow with it and left the headline
136
      sitting on flat ink. It belongs to the words. --%>
137
      <.glow variant={:center} class="hero__glow appear-zoom appear--delay-2" />
138
134 139
      <div class="hero__lede">
135 140
        <div :if={@eyebrow != []} class="hero__eyebrow appear">{render_slot(@eyebrow)}</div>
136 141
        <h1 class="hero__title appear">{@title}</h1>

@@ -337,7 +342,8 @@ defmodule OpenAgentsWeb.UI.Landing do

337 342
  """
338 343
  attr :name, :string, default: "OpenAgents"
339 344
  attr :tagline, :string, default: nil
340
  attr :note, :string, default: nil
345
  attr :note, :string, default: nil, doc: "shown at the trailing edge of the footer bar"
346
  attr :copyright, :string, default: nil, doc: "shown at the leading edge"
341 347
  attr :class, :any, default: nil
342 348
343 349
  slot :column, doc: "one column of links" do

@@ -358,7 +364,13 @@ defmodule OpenAgentsWeb.UI.Landing do

358 364
          {render_slot(column)}
359 365
        </nav>
360 366
      </div>
361
      <p :if={@note} class="landing-footer__note">{@note}</p>
367
      <%!-- Two edges of one bar rather than a single centred line: the
368
      copyright is who owns this, the note is how it is licensed, and reading
369
      them as one sentence makes neither clear. --%>
370
      <div :if={@copyright || @note} class="landing-footer__bar">
371
        <p :if={@copyright} class="landing-footer__note">{@copyright}</p>
372
        <p :if={@note} class="landing-footer__note">{@note}</p>
373
      </div>
362 374
    </footer>
363 375
    """
364 376
  end
lib/openagents_web/live/home_live.ex modified +2 -8

@@ -245,13 +245,6 @@ defmodule OpenAgentsWeb.HomeLive do

245 245
          --%>
246 246
        </Landing.hero>
247 247
248
        <Landing.logo_wall title="Built with">
249
          <:logo>Elixir</:logo>
250
          <:logo>Phoenix</:logo>
251
          <:logo>LiveView</:logo>
252
          <:logo>PostgreSQL</:logo>
253
        </Landing.logo_wall>
254
255 248
        <Landing.feature_grid title="Everything the work needs. Nothing it doesn't.">
256 249
          <:item title="Issues" icon="file-document">
257 250
            Plan, assign, label and close, over an API shaped after the one you already

@@ -303,7 +296,7 @@ defmodule OpenAgentsWeb.HomeLive do

303 296
        </Landing.faq>
304 297
305 298
        <Landing.cta
306
          title="Start shipping"
299
          title="Start shipping."
307 300
          description="Open an issue and let an agent pick it up."
308 301
        >
309 302
          <:actions>

@@ -315,6 +308,7 @@ defmodule OpenAgentsWeb.HomeLive do

315 308
316 309
        <Landing.landing_footer
317 310
          tagline="Purpose-built for planning and shipping issues."
311
          copyright="© 2026 OpenAgents, Inc."
318 312
          note="AGPL-3.0. Every surface here is in the repository."
319 313
        >
320 314
          <:column title="Product">

This page updates live while a promote is in flight · changelog