Nucleus

Color Palette

pacific $brand-primary
  • Links
  • Standard buttons
  • Focused border
  • Selected radio button
  • Progress bar
havasu (pacific w/ 90% white) $brand-primary-lighter
  • Quick Picks hover background
sierra $brand-gray
  • Primary copy
  • ISM selected seat
cascade $brand-gray2
  • Secondary copy
  • Secondary buttons
  • Badge background
  • ISM sold seat
  • Chevron color
  • Dropdown arrow color
rocky $brand-gray3
  • Divider lines
  • Borders
  • Datestamp year background
  • Toggle panel chevron
ridge $brand-gray4
  • Background color
yosemite $brand-cta
  • Checkout/Cart Links
  • Checkout/Cart Buttons
  • Success message
catalina $brand-accent
  • Resale icons
  • Resale seats on ISM
helen $brand-alert
  • Errors
  • Alerts
  • Void buttons

Any color declarations should be using one of the variables described above (states being an exception — see below). You should never use colors outside of this palette.

States

To provide visual cues for interaction, we shade our colors on hover, when disabled, etc. We derive these colors by mixing the core colors with white or black.

25% black Base 50% white 75% white
  • Hover
  • Form placeholder text
  • ISM sections unavailable
  • ISM sections outside of search
  • Disabled
  • Hover
  • ISM seats outside of search
  • Disabled
  • Event header secondary copy
  • Accessibility focus
  • Hover
n/a
  • Disabled
  • Hover
n/a
  • Disabled
n/a
  • ISM Resale seats outside of search
n/a

We have two functions available to calculate these colors: get-darker() and get-lighter(). Each accepts one of the base colors as the first parameter and a percentage as an optional second parameter.

.default-darker {
  // defaults to 25% black
  color: get-darker($brand-primary);
}

.default-lighter {
  // defaults to 75% white
  color: get-lighter($brand-cta);
}

.custom-shade {
  color: get-lighter($brand-accent, 50%);
}
        

Typography

Our web font is TM Sans, a custom typeface created for us by the foundry Monotype.

Responsive fonts

With few exceptions, font sizes on our pages should be responsive at certain breakpoints. You should assume that any font size specified by a designer should be responsive unless explicitly stated otherwise.

To simplify the process of creating responsive fonts, we have a responsive-font() mixin to generate the appropriate code when passed a font size.

Note that we actually specify our font sizes in rem units. 1rem is equivalent to 10px.

// scss
.sample-text {
  @include responsive-font('md');
}
        

Using this mixin, our font sizes are then generated as follows (up to the specified widths).

Breakpoint X-Small Small Medium Large X-Large XX-Large
Small Mobile
≤ 374px
10px font size 12px font size 14px font size 18px font size 22px font size 26px font size
Mobile
375px - 719px
12px font size 14px font size 16px font size 20px font size 24px font size 28px font size
Tablet/Desktop
≥ 720px
no change 16px font size 18px font size 22px font size 26px font size 30px font size
Usage
  • Legal copy
  • Tooltip copy
  • Labels
  • List items
  • Body copy
  • Small auxiliary buttons
  • Event subheader
  • Subheaders
  • Auxiliary buttons
  • Lightbox headers
  • Form fields
  • Tile fields
  • Ticket types (Filters)
  • Event header
  • Qty (Filters)
  • Price (Filters)
  • Sec, Row, Seat (ISM tooltips)
  • Ticket bag
  • Primary headers

And here they are displayed responsively (resize browser window to see):

Extra small copy @include responsive-font('xs');
Small copy @include responsive-font('sm');
Medium copy @include responsive-font('md');
Large copy @include responsive-font('lg');
Extra large copy @include responsive-font('xl');
Extra-extra large copy @include responsive-font('xxl');

Fixed font sizes

In the rare case of using a fixed font size, use our fixed-font() mixin.

It defaults to the md font size. You can override this by passing in a size parameter.

Note that fixed font sizes are based on the mobile breakpoint sizes (375px - 719px), as indicated in the previous section.

Extra small copy 12px @include fixed-font('xs')
Small copy 14px @include fixed-font('sm')
Medium copy 16px @include fixed-font('md')
Large copy 20px @include fixed-font('lg')
Extra large copy 24px @include fixed-font('xl')
Extra-extra large copy 28x @include fixed-font('xxl')
// scss
.fixed-example {
  @include fixed-font('lg');
}

// output
.fixed-example {
  font-size: 1.8rem;
  line-height: 1.2;
}
  

Line Height

By default, line-height for the page is set to 1.4. When using either of the font mixins above, line-height is calculated like so:

Font size is "medium" or lower 1.4
Font size is "large" or higher 1.2

There may be situations where you need a specific line-height other than the above. The mixins have you covered for that, too, by allowing you to pass in a custom line-height value as an optional second parameter.

This can be useful for buttons or other situations where you want the text precisely vertically centered in a "box."

// scss
// note that this also works with responsive-font()
.fixed-example {
  @include fixed-font('lg', 5rem);
}

// output
.fixed-example {
  font-size: 1.8rem;
  line-height: 5rem;
}
        

Text Styles

Primary Header

xx-large, 10px/20px bottom margin, bold, sierra .heading-primary

Secondary Headers

large, 10/20px bottom margin, bold, sierra .heading-secondary
Large body copy large, sierra n/a
Normal body copy medium, sierra applied on .page__content
Alt copy size is based on context, cascade .alt-copy
Legal copy extra small, cascade .legal-copy
Link text underline on hover, pacific <a>

Mixins for text styling

In the case where any of the above use cases is not appropriate, there are mixins available to achieve the desired appearance.

hdg-text mixin

The hdg-text() mixin can be used to create heading text that's bold with a bottom margin of 10px/20px. It is called by passing in a font-size and color. It will automatically make the font responsive via a built-in call to the responsive-font() mixin.

// scss
.some-heading {
  @include hdg-text('md', $black);
}

// output
.some-heading {
  margin-bottom: 5px;
  font-size: 14px;
  font-weight: bold;
  color: #000;
}

@media (min-width: 45em) {
  .some-heading {
    font-size: 16px;
  }
}
        

alt-copy mixin

The alt-copy() mixin can optionally be called with a font-size parameter. By default, font size is not specified and is based on the surrounding font size.

// scss
.ticket-fees {
  @include alt-copy();
}

// output
.ticket-fees {
  font-weight: normal;
  color: #768692;
}
        

Breakpoints

Mobile $bp-xs
Large Mobile $bp-sm
Tablet $bp-md
Desktop $bp-lg
Max $bp-xl

Breakpoint mixin

You can specify media queries by using the breakpoint() mixin.

The mixin accepts two parameters, $min and $max values. By default, if only one parameter is passed, it is assigned to the $min value.

The mixin takes px values and converts them to em units, which is the preferred way to write media queries.

// scss
.some-block {
  margin-top: 15px;

  // $bp-md will be assigned as min-width
  @include breakpoint($bp-md) {
    margin-top: 40px;
  }
}

// output
.some-block {
  margin-top: 15px;
}

// note the conversion to em units
@media (min-width: 45em) {
  .some-block {
    margin-top: 40px;
  }
}
        

If you need to specify the maximum breakpoint instead, you call the mixin by explicity assigning the parameter to $max.

// scss
.another-block {
  [...]

  // here we are explicitly assigning our parameter to $max
  @include breakpoint($max: $bp-lg - 1) {
    padding: 25px;
  }
}

// output
[...]

@media (max-width: 63.6875em) {
  .another-block {
    padding: 25px;
  }
}
        

Note in the above example that we actually passed in ($max: $bp-lg - 1) because we want the styling rules to apply to anything below the max value. (We don't want to actually include the max value as part of the declaration.)

In our example, we're saying applying these rules to anything less than the 1020px width.

Where to Use breakpoint

In SASS, declare your breakpoints within the elements affected. Do not declare media queries as another code block separate from the original context.

// DON'T do this
.class1 {
  font-size: 12px;
}
.class2 {
  padding: 50px;
}

[...]

@include breakpoint($bp-md) {
  .class1 {
    font-size: 18px;
  }
  .class2 {
    padding: 100px;
  }
}

// DO do this
.class1 {
  font-size: 12px;

  @include breakpoint($bp-md) {
    font-size: 18px;
  }
}
          

Grid

We use a Susy-based 12-column grid with 30px gutters.

Page Structure

The basic layout of our pages is as follows:

<body class="page edp">
  <div class="page__wrapper">
    <div class="page__frame">
      <div class="page__content">
        <!-- page content here -->
        
.page Sets base typography for page and background color
.page__wrapper Sets background color for a particular section of the page
.page__frame Sets max-width for your content area
.page__content Sets default font size and other needed attributes for your content area
.[pagename] Sets block context for any page-specific styles

Note that you don't always need to use all of the classes above. Only use those classes that you need to establish page structure.

For example, if you don't need set to a background color for your section of a page that's different from the body background, then you don't need to use page__wrapper. Similarly, if your content is supposed to span the full width of the browser at all times, then you don't need page__frame.

Spacing

Spacing between elements on the page should be one of three possible values, as shown below:

10px $spacing-sm
20px $spacing-md
30px $spacing-lg

In most cases, spacing should be responsive, so at the $bp-md breakpoint, the above values should then be:

15px increase-spacing($spacing-sm)
30px increase-spacing($spacing-md)
45px increase-spacing($spacing-lg)

To make it easier to set responsive spacing, there are two mixins available:

margin-based spacing @include outer-spacing($x)
padding-based spacing @include inner-spacing($y)

Both mixins behave in the same way.

  1. If a single parameter is passed, it will apply the value equally on all four sides.
  2. If you don't want all sides to be uniform, you can assign values to the sides you want to modify.

This is best illustrated with some examples.

// set same margin on all sides
@include outer-spacing($spacing-md);

// set padding on top and bottom
@include inner-spacing($top: $spacing-sm, $bottom: $spacing-sm);

// set padding on top, right, and left
@include inner-spacing($top: $spacing-sm, $right: $spacing-md, $left: $spacing-md)
        

When specifying spacing for any side(s), any side that you omit will be set to 0.

// set 30px bottom margin
.example {
  @include outer-spacing($bottom: $spacing-lg);
}

// output from above will be
.example {
  margin: 0 0 30px 0;
}

@media (min-width: 23.4375em) {
  .example {
    margin: 0 0 45px 0;
  }
}
        

Buttons

Example Classes and dimensions (mobile/desktop)
.button, 44px/46px height, 20px/40px L/R padding
.button, disabled state
.button .button--cta, 44px/46px height, 20/40px L/R padding, bold
.button .button--cta, disabled state
.button .button--static, 20px L/R padding at all times
.button .button--full, 100% width on mobile only
.button-aux, 44px/46px height, 20px/40px L/R padding
.button-aux, disabled state
.button-aux .button-aux--secondary
.button-aux .button-aux--secondary, disabled state
.button-aux .button-aux--full, 100% width on mobile only
.button-aux .button-aux--minor, 30px/40px height, 15/20px L/R padding
.button-outlined, 44px/46px height, 20px/40px L/R padding
.button-outlined, disabled state
.button-outlined .button-outlined--full, 100% width on mobile only
.unbutton, looks like normal link text (needed for accessibility purposes)

Quantity Picker

The following pattern should be used any time a user is prompted to select a quantity, except for the Embedded Quantity Filter (see below).

2

Standard quantity picker.

1

Minimum quantity reached.

50

Maximum quantity reached.

Embedded Quantity Filter

This is a legacy pattern that should only exist for the single ticket type filter on ISM. It should not be used for anything new.

XX Standard Admission
Embedded quantity filter. The item name's width is based on its container.

Lists

Default list styling for lists is as follows:

Unordered List Ordered List
  • list item
  • list item
  • list item
  1. list item
  2. list item
  3. list item

If you want to disable default list style for your use case, use the unstyled-list() mixin.

// scss
.your-list {
  @include unstyled-list();

  // your styles here
}
        

Delimited Lists

The Delimited List pattern has list items separated by a border. Each list item has top and bottom padding, and the list itself has a bottom margin.

All spacing values follow the $spacing-sm rules as described in Spacing.

  • Example 1
  • Second item
  • Last item in list
<ul class="delimited-list">
  <li class="delimited-list__item">
    First item
  </li>
  <li class="delimited-list__item">
    Secondy item
  </li>
  <li class="delimited-list__item">
    Third item
  </li>
</ul>
        

Embedded Delimited List

If you need to embed the Delimited List pattern in a container with a border, you'll need to turn off the bottom margin and apply left and right padding. Otherwise, the list content will be flush against the left and right borders.

Modifying the list to work in this scenario is simple: Just add the --embedded modifier to the list and list items:

<div class="some-box">
  <ul class="delimited-list delimited-list--embedded">
    <li class="delimited-list__item delimited-list__item--embedded">
      First item
    </li>
    <li class="delimited-list__item delimited-list__item--embedded">
      Secondy item
    </li>
    <li class="delimited-list__item delimited-list__item--embedded">
      Third item
    </li>
</div>
        

That'll give you this:

  • Example 1
  • Second item
  • Last item in list

Compact Delimited List

There are occasions when separator lines are not desirable on mobile but are needed on desktop (resize to mobile view to see the difference).

  • Example 1
  • Second item
  • Last item in list
<div class="module">
  <ul class="delimited-list">
    <li class="delimited-list__item delimited-list__item--compact">
      First item
    </li>
    <li class="delimited-list__item delimited-list__item--compact">
      Secondy item
    </li>
    <li class="delimited-list__item delimited-list__item--compact">
      Third item
    </li>
  </div>
</div>
        

Form Elements

Text fields

Example of an the initial state of the input text-field, with fancy (floating) label animation.

<div class="input-group">
  <input id="email" name="email" type="text" class="input-group__text-field">
  <label for="email" class="input-group__label">Email <span class="input-group__required">*</span></label>
</div>
        

Filled input text-fields contains the class has-content, which floats the label

<div class="input-group">
  <input name="email" type="text" class="input-group__text-field has-content" aria-required="true" value="Dohn Joe">
  <label for="email" class="input-group__label">Email <span class="input-group__required">*</span></label>
</div>
        

Same for text-fields in an error state. Only the input field has the class is-error-field

<div class="input-group">
  <input id="email" name="email" type="text" class="input-group__text-field is-error-field">
  <label for="email" class="input-group__label">Email <span class="input-group__required">*</span></label>
</div>
        

Tile Selections

Selected Tile:

-2350 EXP 11/15
Content

Un-Selected Tile:

-2350 EXP 11/15
<div class="tile-selection tile-selection--selected is-clickable">
  <div class="split-content tile-selection__content">
    <div class="split-content__primary tile-selection--selected__primary-heading">
      Primary Heading
    </div>
    <div class="split-content__secondary tile-selection--selected__secondary-heading">
      Secondary Heading
    </div>
  </div>
  <div class="tile-selection__content">
      Content
  </div>
</div>

<div class="tile-selection is-clickable">
  <div class="tile-selection__content">
    -2350 EXP 11/15
  </div>
</div>
        

Tile rendered as a list

  • -2350 EXP 11/15 -2350 EXP 11/15
    Content
  • -2350 EXP 11/15
  • -1234 EXP 8/20
<ul class="sg-unstyled-list">
  <li class="tile-selection tile-selection--selected is-clickable">
    <div class="split-content tile-selection__content">
      <div class="split-content__primary tile-selection--selected__primary-heading">
        Primary Heading
      </div>
      <div class="split-content__secondary tile-selection--selected__secondary-heading">
        Secondary Heading
      </div>
    </div>
    <div class="tile-selection__content">
        Content
    </div>
  </li>

  <li class="tile-selection is-clickable">
    <div class="tile-selection__content">
      -2350 EXP 11/15
    </div>
  </li>
</ul>
        

Tooltips

Tooltip caret size is 10px on mobile, 15px on tablet/desktop. Internal padding of a tooltip follows the 10px/15px spacing rule as described in Spacing.

Default tooltip, with the caret on the bottom

Tooltip with caret on right

Tooltip with caret on left

Tooltip with caret on top

<div class="tooltip">
  <div class="tooltip__content">
    Content goes here.
  </div>
</div>
          

Sec-Row-Seat (SRS)

This is a visual pattern of displaying Section-Row-Seat (SRS) information, used in ISM tooltips and the checkout confirmation page.

The SRS element has a minimum width of 295px, which doesn't account for any padding from its container or the page margins.

Standard ticket header displaying a single ticket

Sec 21
Row 13
Seat 23

Non-contiguous seats

Sec 21 21
Row 13 13
Seat 23 26

Seat range

Sec 21
Row 13
Seat 123-125

Worst case scenario

Sec Loge12
Row 1239
Seat 1809-1813

Layout Patterns

Split Content

This pattern dictates a block of content where one portion (or column) is primary and takes up all available width, while secondary content is only as wide as it needs to be.

The spacing between columns follows the responsive $spacing-sm values as defined in Spacing.

Note how content in this area takes up all available space. Bacon ipsum dolor amet biltong jowl meatball venison rump pig. Short loin ribeye beef ribs brisket pig tail prosciutto short ribs bresaola frankfurter picanha ham.

<div class="module">
  <div class="split-content">
    <div class="split-content__primary module__content">
      [...]
    </div>
    <div class="split-content__secondary module__content">
      [...]
    </div>
  </div>
</div>
        

Secondary content can be placed before or after the primary content.

Note how content in this area takes up all available space. Bacon ipsum dolor amet biltong jowl meatball venison rump pig. Short loin ribeye beef ribs brisket pig tail prosciutto short ribs bresaola frankfurter picanha ham.

<div class="module">
  <div class="split-content module__content">
    <div class="split-content__secondary">
      [...]
    </div>
    <div class="split-content__primary">
      [...]
    </div>
    <div class="split-content__secondary">
      [...]
    </div>
  </div>
</div>
        

If you need content to be top-aligned, use the split-content__primary--top or split-content__secondary--top modifiers.

Bacon ipsum dolor amet pariatur venison meatball, turducken dolore ball tip pork belly ribeye consequat fatback kielbasa ham hock leberkas. Quis non frankfurter fatback, doner in shankle excepteur ut. Kevin dolore short loin quis velit dolor laborum est frankfurter kielbasa voluptate. Doner boudin tempor leberkas beef ribs.

Beef sint et pariatur fatback. Adipisicing frankfurter ut in. Duis ipsum magna qui. Minim spare ribs hamburger, porchetta proident eiusmod et fugiat duis shankle deserunt dolore magna turkey.

<div class="module">
  <div class="split-content module__content">
    <div class="split-content__secondary split-content__secondary--top">
      [...]
    </div>
    <div class="split-content__primary">
      [...]
    </div>
    <div class="split-content__secondary">
      [...]
    </div>
  </div>
</div>
        

Datestamp

Here's how we display event date/time information based on various scenarios.

Variants

Mon 2/24 @ 8:00p

Single date and time

Mon 2/24/15 @ 8:00p

Single date and time with year

Mon 2/24

Single date without time

Mon 6/30 - Wed 7/2

Date range

Mon 12/30/15 - Wed 1/2/16

Date range with one date outside of current year

Mon 3/30/16 - Wed 4/2/16

Date range with dates outside of current year

Multiple Dates & Times

Multiple dates and times

Date & Time TBA

Date and time TBA

Timer

Time left to complete page.
13:49
<div class="timer">
  <div class="is-offscreen">Time left to complete page.</div>
  <div class="timer__indicator">13:49</div>
  <div class="timer__spinner timer__animate"></div>
  <div class="timer__filler timer__animate"></div>
  <div class="timer__bg"></div>
  <div class="timer__mask timer__animate"></div>
</div>

<style>
  // to override default animation duration (i.e. 5s)
  .timer__animate {
      animation-duration: 35s;
  }
</style>
        

Event Headers

Event headers are best illustrated on a separate page.

ISM Tooltips

This pattern utilizes Delimited List, Tooltips, and SRS.

Single Ticket Type

Sec 21
Row 13
Seat 23
  • Standard Ticket
    $100.00

Multiple Ticket Type

Sec 21
Row 13
Seat 23
  • Standard Ticket
    $100.00
  • Child Ticket
    $90.00

With Notes

Sec 21
Row 13
Seat 23
  • Standard Ticket
    $100.00
  • Child Ticket
    $90.00
Obstructed View

General Admission

Sec 21
Row
Seat
  • Standard Ticket
    $100.00 ea
    2
  • Child Ticket
    $90.00 ea
    2
$100.00

Resale

Sec 21
Row J
Seat 14-16
  • Fan-to-Fan Resale
    $100.00 ea
    2
$200.00