[
  {
    "path": ".gitignore",
    "content": "\nStates.sketchplugin.zip\n"
  },
  {
    "path": "Plugin/Debug.xcconfig",
    "content": "// Debug.xcconfig\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#include \"Versioning.xcconfig\"\n\nOTHER_LDFLAGS = $(inherited) -Wl,-source_version -Wl,${IEXP_SOURCE_VERSION}\n"
  },
  {
    "path": "Plugin/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2016 Eden Vidal <edenvidal@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "Plugin/README.md",
    "content": "# States of the artboard — Sketch Plugin\n\nCreate different states and switch between them easily. Just like layer comps for Sketch.\n\n  - Define different positions and toggle visibility of your layers.\n  - Create new states and update changes.\n  - Create pages with new artboards from your states.\n  - Since symbols are artboards, you can create states for them too.\n  - And yes — The states are saved on your file. Boom.\n \n![How it works](https://daks2k3a4ib2z.cloudfront.net/574f0289c3c4633629a7737b/5766c49dc26632fe609656f1_Animation3_03.gif)\n"
  },
  {
    "path": "Plugin/Release.xcconfig",
    "content": "// Release.xcconfig\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#include \"Versioning.xcconfig\"\n\nOTHER_LDFLAGS = $(inherited) -Wl,-source_version -Wl,${IEXP_SOURCE_VERSION}\n"
  },
  {
    "path": "Plugin/States/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2016 Eden Vidal. All rights reserved.</string>\n\t<key>NSPrincipalClass</key>\n\t<string></string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Plugin/States/NSArray+HigherOrder.h",
    "content": "// NSArray+HigherOrder.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Foundation;\n\n@interface NSArray (HigherOrder)\n\n- (nonnull NSArray *)st_map: (nonnull id _Nonnull (^)(id _Nonnull obj))mapper;\n\n- (nonnull NSArray *)st_filter: (nonnull BOOL (^)(id _Nonnull obj))block;\n\n@end\n"
  },
  {
    "path": "Plugin/States/NSArray+HigherOrder.m",
    "content": "// NSArray+HigherOrder.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n\n#import \"NSArray+HigherOrder.h\"\n\n@implementation NSArray (HigherOrder)\n\n- (NSArray *)st_map: (nonnull id _Nonnull (^)(id _Nonnull obj))mapper\n{\n\tNSMutableArray *result = [NSMutableArray arrayWithCapacity: self.count];\n\t[self enumerateObjectsUsingBlock: ^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {\n\t\t[result addObject: mapper(obj)];\n\t}];\n\treturn result;\n}\n\n- (NSArray *)st_filter: (BOOL (^)(id))block\n{\n\tNSMutableArray *new = [NSMutableArray array];\n\t[self enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {\n\t\tif (block(obj)) [new addObject: obj];\n\t}];\n\treturn new;\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/NSArray+Indexes.h",
    "content": "// NSArray+Indexes.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Foundation;\n\n@interface NSArray (Indexes)\n\n- (nonnull NSIndexSet *)st_indexesOfObjects: (nonnull NSArray *)subarray;\n\n@end\n"
  },
  {
    "path": "Plugin/States/NSArray+Indexes.m",
    "content": "// NSArray+Indexes.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"NSArray+Indexes.h\"\n\n@implementation NSArray (Indexes)\n\n- (nonnull NSIndexSet *)st_indexesOfObjects: (nonnull NSArray *)subarray\n{\n\treturn [self indexesOfObjectsPassingTest: ^BOOL(id obj, NSUInteger idx, BOOL * stop) {\n\t\treturn [subarray containsObject: obj];\n\t}];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STArtboard.h",
    "content": "// STArtboard.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Foundation;\n\n@protocol STLayer;\n\n@protocol STArtboard <NSObject, STLayer>\n@optional\n\n- (NSArray <id <STLayer>>*)children;\n\n- (void)setName: (NSString *)name;\n- (NSString *)name;\n\n- (instancetype)copy;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STColorFactory.h",
    "content": "// STColorFactory.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Cocoa;\n\n/// Keeps all of the custom colors for this project\n@interface STColorFactory : NSObject\n\n// Table View Colors\n\n+ (NSColor *)selectedTableViewRowColor;\n\n+ (NSColor *)selectedInactiveTableViewRowColor;\n\n+ (NSColor *)mainTableViewRowColor;\n\n+ (NSColor *)secondaryTableViewRowColor;\n\n+ (NSColor *)tableViewBackgroundColor;\n\n+ (NSColor *)tableViewCellTextRegularColor;\n\n+ (NSColor *)tableViewCellTextSelectedColorWithAlpha: (CGFloat)alpha;\n\n+ (NSColor *)tableViewCellTextInactiveSelectedColorWithAlpha: (CGFloat)alpha;\n\n// Header Colors\n\n+ (NSColor *)headerViewBackgroundColor;\n+ (NSColor *)headerViewBorderColor;\n\n// Placeholder Colors\n\n+ (NSColor *)placeholderViewBackground;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STColorFactory.m",
    "content": "// STColorFactory.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n//\n\n#import \"STColorFactory.h\"\n\n@implementation STColorFactory\n\n+ (NSColor *)selectedTableViewRowColor\n{\n\treturn [NSColor colorWithRed: 110.f/255.f green: 157.f/255.f blue: 228.f/255.f  alpha: 1.0f];\n}\n\n+ (NSColor *)selectedInactiveTableViewRowColor\n{\n\treturn [NSColor colorWithRed: 200.f/255.f green: 200.f/255.f blue: 200.f/255.f  alpha: 1.0f];\n}\n\n+ (NSColor *)tableViewBackgroundColor\n{\n\treturn [NSColor colorWithRed: 236.f/255.f green: 236.f/255.f blue: 236.f/255.f alpha: 1.0f];\n}\n\n+ (NSColor *)mainTableViewRowColor\n{\n\treturn [NSColor colorWithRed: 240.f/255.f green: 240.f/255.f blue: 240.f/255.f alpha: 1.0f];\n}\n\n+ (NSColor *)secondaryTableViewRowColor\n{\n\treturn [NSColor colorWithRed: 235.f/255.f green: 235.f/255.f blue: 235.f/255.f alpha: 1.0f];\n}\n\n+ (NSColor *)tableViewCellTextRegularColor\n{\n\treturn [NSColor controlTextColor];\n}\n\n+ (NSColor *)tableViewCellTextSelectedColorWithAlpha: (CGFloat)alpha\n{\n\treturn [NSColor colorWithWhite: 10 alpha: alpha];\n}\n\n+ (NSColor *)tableViewCellTextInactiveSelectedColorWithAlpha: (CGFloat)alpha\n{\n\treturn [NSColor colorWithWhite: 5 alpha: alpha];\n}\n\n+ (NSColor *)headerViewBackgroundColor\n{\n\treturn [NSColor colorWithRed: 243.f/255.f green: 243.f/255.f blue: 243.f/255.f alpha: 1.0f];\n}\n\n+ (NSColor *)headerViewBorderColor\n{\n\treturn [NSColor colorWithRed: 184.f/255.f green: 184.f/255.f blue: 184.f/255.f alpha: 1.0f];\n}\n\n+ (NSColor *)placeholderViewBackground\n{\n\treturn [NSColor colorWithRed: 236.f/255.f green: 236.f/255.f blue: 236.f/255.f alpha: 1.0f];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STCommand.h",
    "content": "// STCommand.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n\n@import Foundation;\n#import \"STLayer.h\"\n\n@protocol STCommand <NSObject>\n@optional\n\n- (void)setValue: (id)value forKey: (id <NSCopying>)key onLayer: (id <STLayer>)layer;\n- (id)valueForKey: (id <NSCopying>)key onLayer: (id <STLayer>)layer;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STDocument.h",
    "content": "// STDocument.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Foundation;\n#import \"STPage.h\"\n\n@protocol STDocumentData <NSObject>\n\n- (void)addPage: (id <STPage>)page;\n- (void)deselectAllLayers;\n\n@end\n\n@protocol STDocument <NSObject>\n@optional\n\n- (void)setCurrentPage: (id <STPage>)page;\n- (id <STPage>)currentPage;\n\n- (id)window;\n\n- (id <STDocumentData>)documentData;\n\n- (void)setSelectedLayers: (NSArray *)layers;\n\n@end\n\n\n"
  },
  {
    "path": "Plugin/States/STHeaderView.h",
    "content": "// STHeaderView.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Cocoa;\n\n/// A header view with a custom background color\n@interface STHeaderView : NSView\n@end\n"
  },
  {
    "path": "Plugin/States/STHeaderView.m",
    "content": "// STHeaderView.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STColorFactory.h\"\n#import \"STHeaderView.h\"\n\n#define kHeaderViewBorderWidth (1.0f)\n\n@implementation STHeaderView\n\n- (void)awakeFromNib\n{\n\tself.wantsLayer = YES;\n}\n\n- (BOOL)wantsUpdateLayer\n{\n\treturn YES;\n}\n\n- (void)updateLayer\n{\n\t// Setup a background\n\tself.layer.backgroundColor = [STColorFactory headerViewBackgroundColor].CGColor;\n\t// Draw a border at the buttom of the header\n\tCALayer *buttomBorder = [CALayer layer];\n\tbuttomBorder.borderColor = [STColorFactory headerViewBorderColor].CGColor;\n\tbuttomBorder.borderWidth = kHeaderViewBorderWidth;\n\tbuttomBorder.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), kHeaderViewBorderWidth);\n\n\t[self.layer addSublayer: buttomBorder];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STLayer.h",
    "content": "// STLayer.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Foundation;\n\n@protocol STAbsoluteRect;\n\n@protocol STLayer <NSObject>\n@optional\n\n- (BOOL)isVisible;\n- (void)setIsVisible: (BOOL)visible;\n- (id <STAbsoluteRect>)absoluteRect;\n\n- (void)copyToLayer: (id <STLayer>)newParent beforeLayer: (id <STLayer>)sibling;\n\n@end\n\n@protocol STFrame <NSObject>\n@optional\n\n- (CGRect)rect;\n\n- (CGFloat)x;\n- (CGFloat)y;\n\n- (void)setX: (CGFloat)x;\n- (void)setY: (CGFloat)y;\n\n@end\n\n@protocol STAbsoluteRect <NSObject>\n@optional\n\n- (CGRect)absoluteRect;\n\n- (void)setX: (CGFloat)x;\n- (void)setY: (CGFloat)y;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STLayerState.h",
    "content": "// STLayerState.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Foundation;\n\n@protocol STLayer;\n\n/// Incapsulates a state of a single layer: its frame and visibility status\n@interface STLayerState : NSObject\n\n@property (readonly) NSRect frame;\n@property (readonly) BOOL visible;\n\n- (instancetype)initWithFrame: (NSRect)aFrame visibilityStatus: (BOOL)visible;\n+ (instancetype)stateWithFrame: (NSRect)aFrame visibilityStatus: (BOOL)visible;\n\n- (NSDictionary <NSString *, id> *)dictionaryRepresentation;\n- (instancetype)initWithDictionary: (NSDictionary <NSString *, id> *)dictionary;\n\n@end\n\n/// Applies the given layer state to the given layer\n@interface STLayerStateApplier : NSObject\n+ (void)apply: (STLayerState *)state toLayer: (id <STLayer>)layer;\n@end\n\n/// Returns the current layer's state\n@interface STLayerStateFetcher : NSObject\n+ (STLayerState *)fetchStateFromLayer: (id <STLayer>)layer;\n@end\n\n/// Verifies that the given layer conforms to the given state\n@interface STLayerStateExaminer : NSObject\n+ (BOOL)layer: (id <STLayer>)layer conformsToState: (STLayerState *)state;\n@end\n"
  },
  {
    "path": "Plugin/States/STLayerState.m",
    "content": "// STLayerState.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STLayer.h\"\n#import \"STLayerState.h\"\n\n@implementation STLayerState\n\n- (instancetype)initWithFrame: (NSRect)aFrame visibilityStatus: (BOOL)visible\n{\n\tif ((self = [super init])) {\n\t\t_frame = aFrame;\n\t\t_visible = visible;\n\t}\n\treturn self;\n}\n\n+ (instancetype)stateWithFrame: (NSRect)aFrame visibilityStatus: (BOOL)visible\n{\n\treturn [[[self class] alloc] initWithFrame: aFrame visibilityStatus: visible];\n}\n\n- (NSDictionary <NSString *, id> *)dictionaryRepresentation\n{\n\treturn @{\n\t\t@\"frame\" : NSStringFromRect(_frame),\n\t\t@\"visible\" : @(_visible)\n\t};\n}\n\n- (instancetype)initWithDictionary: (NSDictionary <NSString *, id> *)dictionary\n{\n\tNSParameterAssert(dictionary[@\"frame\"]);\n\tNSParameterAssert(dictionary[@\"visible\"]);\n\n\treturn [self initWithFrame: NSRectFromString(dictionary[@\"frame\"])\n\t\t\t  visibilityStatus: [dictionary[@\"visible\"] boolValue]];\n}\n\n- (BOOL)isEqual: (id)object\n{\n\ttypeof(self) another = object;\n\n\tif (![another isKindOfClass: [self class]]) {\n\t\treturn NO;\n\t}\n\tif (!NSEqualRects(_frame, another.frame)) {\n\t\treturn NO;\n\t}\n\tif (_visible != another.visible) {\n\t\treturn NO;\n\t}\n\treturn YES;\n}\n\n- (NSUInteger)hash\n{\n\treturn NSStringFromRect(_frame).hash + @(_visible).hash;\n}\n\n- (NSString *)description\n{\n\treturn [NSString stringWithFormat: @\"<%@: %p> (frame = %@, visible = %@)\",\n\t\t\tNSStringFromClass([self class]), (void *)self,\n\t\t\tNSStringFromRect(_frame), _visible ? @\"YES\" : @\"NO\"];\n}\n\n@end\n\n@implementation STLayerStateApplier\n\n+ (void)apply: (STLayerState *)state toLayer: (id <STLayer>)layer\n{\n\tlayer.isVisible = state.visible;\n\n\tid <STFrame> frame = [layer performSelector: @selector(frame)];\n\tframe.x = state.frame.origin.x;\n\tframe.y = state.frame.origin.y;\n}\n\n@end\n\n@implementation STLayerStateFetcher : NSObject\n\n+ (STLayerState *)fetchStateFromLayer: (id <STLayer>)layer\n{\n\tid <STFrame> frameObject = [layer performSelector: @selector(frame)];\n\treturn [[STLayerState alloc] initWithFrame: NSRectFromCGRect(frameObject.rect)\n\t\t\t\t\t\t\t  visibilityStatus: layer.isVisible];\n}\n\n@end\n\n@implementation STLayerStateExaminer : NSObject\n\n+ (BOOL)layer: (id <STLayer>)layer conformsToState: (STLayerState *)state\n{\n\tid <STFrame> frameObject = [layer performSelector: @selector(frame)];\n\tNSRect layerRect = NSRectFromCGRect(frameObject.rect);\n\n\tif (layer.isVisible != state.visible) {\n\t\treturn NO;\n\t}\n\tif (!NSEqualPoints(layerRect.origin, state.frame.origin)) {\n\t\treturn NO;\n\t}\n\treturn YES;\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STPage.h",
    "content": "// STPage.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Foundation;\n#import \"STArtboard.h\"\n\n@protocol STPage <NSObject, STLayer>\n@optional\n\n+ (instancetype)page;\n- (instancetype)copy;\n\n- (id <STArtboard>)currentArtboard;\n- (NSArray *)artboards;\n\n- (void)enumerateLayersWithOptions: (int)options block: (void(^)(id <STLayer> layer))block;\n\n- (void)addLayers: (NSArray *)layers;\n- (void)removeLayer: (id <STLayer>)layer;\n\n- (void)selectLayers: (NSArray *)layers;\n\n- (void)setName: (NSString *)name;\n- (NSString *)name;\n\n- (void)setPageDelegate: (id)pageDelegate;\n- (id)pageDelegate;\n\n- (void)setGrid: (id)grid;\n- (id)grid;\n\n- (void)setLayout: (id)layout;\n- (id)layout;\n\n- (void)setScrollOrigin: (CGPoint)scrollOrigin;\n- (CGPoint)scrollOrigin;\n\n- (void)setZoomValue: (CGFloat)zoomValue;\n- (CGFloat)zoomValue;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STPlaceholderView.h",
    "content": "// STPlaceholderView.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Cocoa;\n\n/// A simple placeholder view that covers the main table view when there's no artboard selected\n@interface STPlaceholderView : NSView\n@end\n"
  },
  {
    "path": "Plugin/States/STPlaceholderView.m",
    "content": "// STPlaceholderView.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n\n#import \"STColorFactory.h\"\n#import \"STPlaceholderView.h\"\n\n@implementation STPlaceholderView\n\n- (void)awakeFromNib\n{\n\tself.wantsLayer = YES;\n}\n\n- (BOOL)wantsUpdateLayer\n{\n\treturn YES;\n}\n\n- (void)updateLayer\n{\n\tself.layer.backgroundColor = [STColorFactory placeholderViewBackground].CGColor;\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STSketch.h",
    "content": "// STSketch.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Cocoa;\n#import \"STStateDescription.h\"\n#import \"STDocument.h\"\n#import \"STSketchPluginContext.h\"\n\n@protocol SketchNotificationsListener <NSObject>\n@required\n- (void)currentArtboardDidChange;\n- (void)currentArtboardUnselected;\n- (void)currentDocumentUpdated;\n@end\n\n/// The bridge between Sketch and our plugin. Provides info about current document as well\n/// as various notifications available for SketchNotificationsListener\n@interface STSketch : NSObject\n\n/// Information about the curent document: the document itself, current page and artboard\n+ (id <STDocument>)currentDocument;\n+ (id <STPage>)currentPage;\n+ (id <STArtboard>)currentArtboard;\n\n/// Use this observer to subscribe to various Sketch notifications. See SketchNotificationsListener\n/// for more details\n+ (instancetype)notificationObserver;\n- (void)addListener: (id <SketchNotificationsListener>)listener;\n\n/// We must save a plugin context in order to perform some layer modifications (i.e. use plugin command)\n/// IMPORTANT: You must set this context via -setPluginContext: method before calling any other methods\n/// of this class.\n+ (void)setPluginContextDictionary: (NSDictionary *)contextDictionary;\n+ (STSketchPluginContext *)pluginContext;\n\n/// Toggles the plugin's menu item's titles between \"Show States\" and \"Hide States\"\n+ (void)toggleStatesPluginName;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STSketch.m",
    "content": "// STSketch.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import <objc/runtime.h>\n#import \"Aspects.h\"\n#import \"STSketch.h\"\n#import \"STStatefulArtboard.h\"\n\n@interface STSketch()\n@property (strong) NSHashTable *listeners;\n@end\n\n@implementation STSketch\n\n+ (instancetype)notificationObserver\n{\n\tstatic STSketch *observer = nil;\n\tstatic dispatch_once_t onceToken;\n\tdispatch_once(&onceToken, ^{\n\t\tobserver = [STSketch new];\n\t\tobserver.listeners = [NSHashTable weakObjectsHashTable];\n\t\t[observer injectIntoMSDocument];\n\t});\n\treturn observer;\n}\n\n- (void)addListener: (id)listener\n{\n\t[_listeners addObject: listener];\n}\n\n#pragma mark -\n\n+ (id <STDocument>)currentDocument\n{\n\treturn [NSClassFromString(@\"MSDocument\") currentDocument];\n}\n\n+ (id <STPage>)currentPage\n{\n\treturn [[self currentDocument] currentPage];\n}\n\n+ (id <STArtboard>)currentArtboard\n{\n\tid <STArtboard> raw = [[self currentPage] currentArtboard];\n\tif (!raw) {\n\t\treturn nil;\n\t}\n\treturn [[STStatefulArtboard alloc] initWithArtboard: raw context: [self pluginContext]];\n}\n\n#pragma mark -\n\n+ (void)setPluginContextDictionary: (NSDictionary *)contextDictionary;\n{\n\tSTSketchPluginContext *context = [[STSketchPluginContext alloc] initWithData: contextDictionary];\n\tobjc_setAssociatedObject(self, @selector(pluginContext), context, OBJC_ASSOCIATION_RETAIN);\n}\n\n+ (instancetype)pluginContext\n{\n\tid context = objc_getAssociatedObject(self, @selector(pluginContext));\n\tNSAssert(context != nil, @\"You must set pluginContext via [%@ setPluginContext:] method before calling any other methods of this class\", [self class]);\n\treturn context;\n}\n\n#pragma mark -\n\n+ (void)toggleStatesPluginName\n{\n    NSMenu *pluginsMenu = [[NSApp menu] itemWithTitle: @\"Plugins\"].submenu;\n    NSMenuItem *currentStatesItem = nil;\n    if ((currentStatesItem = [pluginsMenu itemWithTitle: @\"Show States\"])) {\n        currentStatesItem.title = @\"Hide States\";\n    } else if ((currentStatesItem = [pluginsMenu itemWithTitle: @\"Hide States\"])) {\n\t\tcurrentStatesItem.title = @\"Show States\";\n    } else {\n        NSAssert(currentStatesItem, @\"Could not find States plugin menu item inside Plugins menu\");\n    }\n}\n\n#pragma mark -\n\n/// Inject ourselves into Sketch internals to receive notifications about artboard selection\n/// and document changes\n- (void)injectIntoMSDocument\n{\n\tClass MSDocument = NSClassFromString(@\"MSDocument\");\n\tClass _MSLayer = NSClassFromString(@\"_MSLayer\");\n\tClass MSPage = NSClassFromString(@\"MSPage\");\n\tClass _MSImmutableLayer = NSClassFromString(@\"_MSImmutableLayer\");\n\n\t[[NSNotificationCenter defaultCenter] addObserverForName: NSWindowWillCloseNotification\n\t\t\t\t\t\t\t\t\t\t\t\t\t  object: [[STSketch currentDocument] window]\n\t\t\t\t\t\t\t\t\t\t\t\t\t   queue: [NSOperationQueue mainQueue]\n\t\t\t\t\t\t\t\t\t\t\t\t  usingBlock: ^(NSNotification * _Nonnull note)\n\t {\n\t\t for (id <SketchNotificationsListener> listener in [_listeners allObjects]) {\n\t\t\t [listener currentArtboardUnselected];\n\t\t }\n\t}];\n\n\tSEL currentArtboardDidChangeSelector = NSSelectorFromString(@\"currentArtboardDidChange\");\n\t[MSDocument aspect_hookSelector: currentArtboardDidChangeSelector withOptions: AspectPositionAfter usingBlock: ^(id<AspectInfo> aspectInfo)\n\t {\n\t\t NSAssert(aspectInfo.instance == [STSketch currentDocument],\n\t\t\t\t  @\"Unexpected artboard selection update from a secondary document\");\n\t\t for (id <SketchNotificationsListener> listener in [_listeners allObjects]) {\n\t\t\t [listener currentArtboardDidChange];\n\t\t }\n\t } error: NULL];\n\n\t[MSDocument aspect_hookSelector: @selector(windowDidBecomeKey:) withOptions: AspectPositionAfter usingBlock: ^(id<AspectInfo> aspectInfo)\n\t {\n\t\t // Wait until the next run loop iteration to let Sketch switch to a new document\n\t\t dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{\n\t\t\t for (id <SketchNotificationsListener> listener in [_listeners allObjects]) {\n\t\t\t\t [listener currentArtboardDidChange];\n\t\t\t }\n\t\t });\n\t } error: NULL];\n\n\t/// XXX\n\tSEL setCurrentArtboard = NSSelectorFromString(@\"setCurrentArtboard:\");\n\t[MSPage aspect_hookSelector: setCurrentArtboard withOptions: AspectPositionAfter usingBlock: ^(id<AspectInfo> aspectInfo)\n\t {\n\t\t id artboard = [[aspectInfo arguments] firstObject];\n\t\t for (id <SketchNotificationsListener> listener in [_listeners allObjects]) {\n\t\t\t if (!artboard) {\n\t\t\t\t [listener currentArtboardUnselected];\n\t\t\t } else {\n\t\t\t\t [listener currentArtboardDidChange];\n\t\t\t }\n\t\t }\n\t } error: NULL];\n\n\tClass MSDocumentData = NSClassFromString(@\"MSDocumentData\");\n\tSEL changeSelectionTo = NSSelectorFromString(@\"changeSelectionTo:\");\n\t[MSDocumentData aspect_hookSelector: changeSelectionTo withOptions: AspectPositionAfter usingBlock: ^(id<AspectInfo> aspectInfo)\n\t {\n\t\t NSArray *selection = [[aspectInfo arguments] firstObject];\n\t\t if (![selection isKindOfClass: [NSArray class]]) {\n\t\t\t return;\n\t\t }\n\t\t for (id <SketchNotificationsListener> listener in [_listeners allObjects]) {\n\t\t\t if (selection.count != 0) {\n\t\t\t\t[listener currentArtboardDidChange];\n\t\t\t }\n\t\t }\n\t } error: NULL];\n\n\n\t/// XXX\n\tvoid (^documentUpdateHandler)(void) = ^(void) {\n\t\tfor (id <SketchNotificationsListener> listener in [_listeners allObjects]) {\n\t\t\t[listener currentDocumentUpdated];\n\t\t}\n\t};\n\n\t// XXX\n\tSEL layerPositionPossiblyChanged = NSSelectorFromString(@\"layerPositionPossiblyChanged\");\n\t[MSDocument aspect_hookSelector: layerPositionPossiblyChanged withOptions: AspectPositionAfter usingBlock: ^(id<AspectInfo> aspectInfo)\n\t {\n\t\t id <STDocument> doc = aspectInfo.instance;\n\t\t if ([[doc currentPage] currentArtboard] == [[STSketch currentPage] currentArtboard]) {\n\t\t\t documentUpdateHandler();\n\t\t }\n\t } error: NULL];\n\n\t// XXX\n\t[MSDocument aspect_hookSelector: NSSelectorFromString(@\"undoAction:\") withOptions: AspectPositionAfter usingBlock: ^(id<AspectInfo> aspectInfo)\n\t {\n\t\t id <STDocument> doc = aspectInfo.instance;\n\t\t if ([[doc currentPage] currentArtboard] == [[STSketch currentPage] currentArtboard]) {\n\t\t\t documentUpdateHandler();\n\t\t }\n\t } error: NULL];\n\n\t/// XXX\n\tSEL setIsVisible = NSSelectorFromString(@\"setIsVisible:\");\n\t[_MSImmutableLayer aspect_hookSelector: setIsVisible withOptions: AspectPositionAfter usingBlock: ^(id<AspectInfo> aspectInfo)\n\t {\n\t\t documentUpdateHandler();\n\t } error: NULL];\n\n\t[_MSLayer aspect_hookSelector: setIsVisible withOptions: AspectPositionAfter usingBlock: ^(id<AspectInfo> aspectInfo)\n\t {\n\t\t documentUpdateHandler();\n\t } error: NULL];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STSketchPluginContext.h",
    "content": "// SketchPluginContext.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Foundation;\n#import \"STDocument.h\"\n#import \"STCommand.h\"\n\n/// Encapsulate a Sketch plugin context dictionary\n@interface STSketchPluginContext : NSObject\n\n@property (readonly, strong) id pluginBundle;\n@property (readonly, strong) id <STDocument> document;\n@property (readonly, strong) id <STCommand> command;\n\n- (instancetype)initWithData: (NSDictionary *)data;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STSketchPluginContext.m",
    "content": "// SketchPluginContext.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STSketchPluginContext.h\"\n\n@interface STSketchPluginContext()\n@property (readwrite, strong) id pluginBundle;\n@property (readwrite, strong) id <STDocument> document;\n@property (readwrite, strong) id <STCommand> command;\n@end\n\n@implementation STSketchPluginContext\n\n- (instancetype)initWithData: (NSDictionary *)data\n{\n\tif ((self = [super init])) {\n\t\t_pluginBundle = data[@\"plugin\"];\n\t\t_document = data[@\"document\"];\n\t\t_command = data[@\"command\"];\n\t}\n\treturn self;\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STStateDescription.h",
    "content": "// STStateDescription.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Foundation;\n\n/// Represents a State model. Each state has a title and an unique identifier.\n@interface STStateDescription : NSObject\n\n@property (readonly, copy) NSString *title;\n@property (readonly, copy) NSUUID *UUID;\n\n/// Returns a new state description with the given title and random UUID\n- (instancetype)initWithTitle: (NSString *)title;\n/// Returns a new state description from the given dictionary.\n/// Expected keys: \"title\" and \"UUID\".\n- (instancetype)initWithDictionary: (NSDictionary <NSString *, id> *)dictionaryRepresentation;\n\n/// Returns a copy of the current state with the same UUID but different title. You're supposed\n/// to replace all copies of the old state with the new one.\n- (instancetype)stateByAlteringTitle: (NSString *)title;\n/// Returns a new state with random UUID and title equal to the current state's title with \" Copy\" suffix\n- (instancetype)duplicate;\n\n/// Returns a dictionary representation of this state model\n- (NSDictionary <NSString *, id> *)dictionaryRepresentation;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STStateDescription.m",
    "content": "// STStateDescription.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STStateDescription.h\"\n\n@interface STStateDescription()\n@property (readwrite, copy) NSString *title;\n@property (readwrite, copy) NSUUID *UUID;\n@end\n\n@implementation STStateDescription\n\n- (instancetype)initWithTitle: (NSString *)title\n{\n\tif ((self = [super init])) {\n\t\tself.UUID = [NSUUID UUID];\n\t\tself.title = title;\n\t}\n\treturn self;\n}\n\n- (instancetype)initWithTitle: (NSString *)title UUID: (NSUUID *)UUID\n{\n\tif ((self = [self initWithTitle: title])) {\n\t\tself.UUID = UUID;\n\t}\n\treturn self;\n}\n\n- (instancetype)initWithDictionary: (NSDictionary <NSString *, id> *)dictionaryRepresentation\n{\n\tNSParameterAssert(dictionaryRepresentation[@\"title\"] != nil);\n\tNSParameterAssert(dictionaryRepresentation[@\"UUID\"] != nil);\n\n\tNSString *title = dictionaryRepresentation[@\"title\"];\n\tNSUUID *UUID = [[NSUUID alloc] initWithUUIDString: dictionaryRepresentation[@\"UUID\"]];\n\n\treturn [self initWithTitle: title UUID: UUID];\n}\n\n- (NSDictionary <NSString *, id> *)dictionaryRepresentation\n{\n\treturn @{\n\t\t@\"title\": self.title,\n\t\t@\"UUID\" : self.UUID.UUIDString\n\t};\n}\n\n- (instancetype)stateByAlteringTitle: (NSString *)title\n{\n\tSTStateDescription *newState = [[STStateDescription alloc] initWithTitle: title];\n\tnewState.UUID = self.UUID;\n\treturn newState;\n}\n\n- (instancetype)duplicate\n{\n\treturn [[STStateDescription alloc] initWithTitle: self.title];\n}\n\n- (BOOL)isEqual: (id)object\n{\n\ttypeof(self) another = object;\n\n\tif (![another isKindOfClass: [self class]]) {\n\t\treturn NO;\n\t}\n\n\tif (![another.UUID isEqual: self.UUID]) {\n\t\treturn NO;\n\t}\n\n\tif (![another.title isEqualToString: self.title]) {\n\t\treturn NO;\n\t}\n\treturn YES;\n}\n\n- (NSUInteger)hash\n{\n\treturn self.UUID.hash + self.title.hash;\n}\n\n- (NSString *)description\n{\n\treturn [NSString stringWithFormat: @\"<%@: %p> (UUID = %@, title = \\\"%@\\\" @ %p)\",\n\t\t\tNSStringFromClass([self class]), (void *)self, self.UUID.UUIDString, self.title, (void *)self.title];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STStatefulArtboard+Backend.h",
    "content": "// STStatefulArtboard+Backend.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STStatefulArtboard.h\"\n\n/// STStatefulArtboard extension that allows to save data inside Sketch metadata\n@interface STStatefulArtboard (Backend)\n\n- (nonnull NSArray <NSDictionary *> *)artboardStatesData;\n- (void)setArtboardStatesData: (nonnull NSArray <NSDictionary *> *)newData;\n\n- (nonnull NSDictionary <NSString *, id> *)artboardCurrentStateData;\n- (void)setArtboardCurrentStateData: (nonnull NSDictionary <NSString *, id> *)newData;\n\n- (nonnull NSDictionary <NSString *, id> *)metadataForLayer: (nonnull id <STLayer>)layer;\n- (void)setMedatada: (nonnull NSDictionary <NSString *, id> *)newMetadata forLayer: (nonnull id <STLayer>)layer;\n\n- (nonnull NSDictionary <NSString *, id> *)artboardDefaultStateData;\n- (void)setArtboardDefaultStateData: (nonnull NSDictionary <NSString *, id> *)newData;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STStatefulArtboard+Backend.m",
    "content": "// STStatefulArtboard+Backend.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STStatefulArtboard+Backend.h\"\n\nstatic NSString const *const kSTStatefulArtboardStatesKey       = @\"x-states-states\";\nstatic NSString const *const kSTStatefulArtboardStateValuesKey  = @\"x-states-state-values\";\nstatic NSString const *const kSTStatefulArtboardCurrentStateKey = @\"x-states-current-state\";\nstatic NSString const *const kSTStatefulArtboardDefaultStateKey = @\"x-states-default-state\";\n\n@implementation STStatefulArtboard (Backend)\n\n- (NSArray <NSDictionary *> *)artboardStatesData\n{\n\treturn [[self.context command] valueForKey: kSTStatefulArtboardStatesKey onLayer: _internal] ?: @[];\n}\n\n- (void)setArtboardStatesData: (NSArray <NSDictionary *> *)newData\n{\n\t[[self.context command] setValue: newData forKey: kSTStatefulArtboardStatesKey onLayer: _internal];\n}\n\n- (NSDictionary <NSString *, id> *)artboardCurrentStateData\n{\n\treturn [[self.context command] valueForKey: kSTStatefulArtboardCurrentStateKey onLayer: _internal] ?: @{};\n}\n\n- (void)setArtboardCurrentStateData: (NSDictionary <NSString *, id> *)newData\n{\n\t[[self.context command] setValue: newData forKey: kSTStatefulArtboardCurrentStateKey onLayer: _internal];\n}\n\n- (NSDictionary <NSString *, id> *)metadataForLayer: (id <STLayer>)layer\n{\n\treturn [[self.context command] valueForKey: kSTStatefulArtboardStateValuesKey onLayer: layer] ?: @{};\n}\n\n- (void)setMedatada: (NSDictionary <NSString *, id> *)newMetadata forLayer: (id <STLayer>)layer\n{\n\t[[self.context command] setValue: newMetadata forKey: kSTStatefulArtboardStateValuesKey onLayer: layer];\n}\n\n- (nonnull NSDictionary <NSString *, id> *)artboardDefaultStateData\n{\n\treturn [[self.context command] valueForKey: kSTStatefulArtboardDefaultStateKey onLayer: _internal] ?: @{};\n}\n\n- (void)setArtboardDefaultStateData: (nonnull NSDictionary <NSString *, id> *)newData\n{\n\t[[self.context command] setValue: newData forKey: kSTStatefulArtboardDefaultStateKey onLayer: _internal];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STStatefulArtboard+Snapshots.h",
    "content": "// STStatefulArtboard+Snapshots.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STStatefulArtboard.h\"\n\n@interface STStatefulArtboard (Snapshots)\n\n/// Returns a new artboard reflecting the given state. All states metadata will be lost (i.e. it\n/// will be \"clean\" snapshot)\n- (id <STArtboard>)snapshotForState: (STStateDescription *)state;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STStatefulArtboard+Snapshots.m",
    "content": "// STStatefulArtboard+Snapshots.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STLayerState.h\"\n#import \"NSArray+HigherOrder.h\"\n#import \"STStatefulArtboard+Backend.h\"\n#import \"STStatefulArtboard+Snapshots.h\"\n\n@implementation STStatefulArtboard (Snapshots)\n\n- (id <STArtboard>)snapshotForState: (STStateDescription *)state\n{\n\tNSParameterAssert([self.allStates containsObject: state]);\n\n\tid <STArtboard> snapshotInternal = [_internal copy];\n\tsnapshotInternal.name = state.title;\n\n\tSTStatefulArtboard *snapshot = [[STStatefulArtboard alloc] initWithArtboard: snapshotInternal\n                                                                        context: self.context];\n\n\t[snapshot applyState: state];\n\t[snapshot removeAllStates];\n\n\treturn snapshotInternal;\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STStatefulArtboard.h",
    "content": "// StatefulArtboard.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n\n@import Foundation;\n#import \"STStateDescription.h\"\n#import \"STSketchPluginContext.h\"\n#import \"STArtboard.h\"\n\n/// A wrapper around Sketch's artboard which provides methods for manipulating its state\n@interface STStatefulArtboard : NSObject <STArtboard>\n{\n@protected\n\tid <STArtboard> _internal;\n}\n@property (readonly, strong) STSketchPluginContext *context;\n@property (readonly, strong) NSArray <STStateDescription *> *allStates;\n@property (readonly, strong) STStateDescription *currentState;\n@property (readonly, strong) STStateDescription *defaultState;\n\n- (instancetype)initWithArtboard: (id <STArtboard>)artboard context: (STSketchPluginContext *)context;\n\n/// Verifies that all of this artboard's child layers conforms to the given state model\n- (BOOL)conformsToState: (STStateDescription *)state;\n\n/// Restore artboard state from `state`\n- (void)applyState: (STStateDescription *)state;\n\n/// Save current artboard state\n- (void)updateCurrentState;\n\n/// Inserts a new state model into this artboard's metadata. This new state model will represent\n/// the current state of the artboard\n- (void)insertNewState: (STStateDescription *)newState;\n\n/// Rewrites all child layers attribites so that the `destination` state becomes equal to the `source` one\n- (void)copyState: (STStateDescription *)source toState: (STStateDescription *)destination;\n\n/// Update the given state's name in this artboard's metadata\n- (STStateDescription *)updateName: (NSString *)newName forState: (STStateDescription *)existingState;\n\n/// Changes the order of the states in this artboard. A passed array must include all of the states\n/// of this artboard and nothing else\n- (void)reorderStates: (NSArray <STStateDescription *> *)allStatesInNewOrder;\n\n/// Completely removes the given state from this artboard\n- (void)removeState: (STStateDescription *)stateToRemove;\n\n/// Wipes all of the states\n- (void)removeAllStates;\n\n/// WARNING: you're not suppposed to call this method. It's here just so -[StatesContoller createNewState:]\n/// may call it and workaround a major performance issue with applying states on really big artboards.\n/// Eventually this method will go away.\n- (void)setCurrentState: (STStateDescription *)currentState;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STStatefulArtboard.m",
    "content": "// StatefulArtboard.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STStatefulArtboard.h\"\n#import \"STStatefulArtboard+Backend.h\"\n#import \"STLayerState.h\"\n#import \"NSArray+HigherOrder.h\"\n\n#define kArtboardDefaultStateTitle @\"Initial State\"\n\n@implementation STStatefulArtboard\n\n- (instancetype)initWithArtboard: (id <STArtboard>)artboard context: (STSketchPluginContext *)context\n{\n\tNSParameterAssert(artboard != nil);\n\tNSParameterAssert(context != nil);\n\n\tif ((self = [super init])) {\n\t\t_internal = artboard;\n\t\t_context = context;\n\t\t[self createDefaultStateIfNeeded];\n\t}\n\treturn self;\n}\n\n- (void)createDefaultStateIfNeeded\n{\n\tif (self.allStates.count > 0) {\n\t\t// Backwards compatibility\n\t\tif (!self.defaultState) {\n\t\t\t[self setDefaultState: self.allStates.firstObject];\n\t\t}\n\t} else {\n\t\tSTStateDescription *defaultState = [[STStateDescription alloc] initWithTitle: kArtboardDefaultStateTitle];\n\t\t[self insertNewState: defaultState];\n\t\t[self setCurrentState: defaultState];\n\t\t[self setDefaultState: defaultState];\n\t}\n}\n\n#pragma mark - STLayer\n\n- (NSArray <id <STLayer>> *)children\n{\n\treturn [[_internal children] st_filter: ^BOOL(id child) {\n\t\treturn [child class] != NSClassFromString(@\"MSArtboardGroup\");\n\t}];\n}\n\n#pragma mark - Actions\n\n- (BOOL)conformsToState: (STStateDescription *)state\n{\n\tif (![self.allStates containsObject: state]) {\n\t\treturn NO;\n\t}\n\n\t__block BOOL result = YES;\n\t[[self children] enumerateObjectsUsingBlock: ^(id<STLayer> layer, NSUInteger idx, BOOL *stop) {\n\t\tNSDictionary *metadata = [self metadataForLayer: layer][state.UUID.UUIDString];\n\t\tif (metadata.count == 0) {\n\t\t\tresult = NO; *stop = YES;\n\t\t\treturn;\n\t\t}\n\t\tSTLayerState *layerState = [[STLayerState alloc] initWithDictionary: metadata];\n\t\tif (!layerState || ![STLayerStateExaminer layer: layer conformsToState: layerState]) {\n\t\t\tresult = NO; *stop = YES;\n\t\t}\n\t}];\n\treturn result;\n}\n\n- (void)removeAllStates\n{\n\t[self setArtboardStatesData: @[]];\n\t[self setArtboardCurrentStateData: @{}];\n\t[self setArtboardDefaultStateData: @{}];\n\t[[self children] enumerateObjectsUsingBlock: ^(id<STLayer> layer, NSUInteger idx, BOOL *stop) {\n\t\t[self setMedatada: @{} forLayer: layer];\n\t}];\n\t// Re-create the initial state\n\t[self createDefaultStateIfNeeded];\n}\n\n- (void)removeState: (STStateDescription *)stateToRemove\n{\n\tNSParameterAssert(stateToRemove != nil);\n\t\n\tif ([stateToRemove isEqual: self.currentState]) {\n\t\tNSInteger idx = [self.allStates indexOfObject: self.currentState];\n\t\tNSInteger previousStateIdx = idx - 1;\n\t\tNSInteger nextStateIdx = idx + 1;\n\t\tif (previousStateIdx >= 0) {\n\t\t\t[self applyState: self.allStates[previousStateIdx]];\n\t\t} else if (nextStateIdx < self.allStates.count) {\n\t\t\t[self applyState: self.allStates[nextStateIdx]];\n\t\t} else {\n\t\t\t[self setArtboardCurrentStateData: @{}];\n\t\t}\n\t}\n\n\t// 1) Remove from artboard state descriptions\n\tNSArray *statesToKeep = [[self artboardStatesData] st_filter: ^BOOL(NSDictionary *item) {\n\t\treturn [item isNotEqualTo: stateToRemove.dictionaryRepresentation];\n\t}];\n\t[self setArtboardStatesData: statesToKeep];\n\t// 2) Remove this state's metadata from layers\n\t[[self children] enumerateObjectsUsingBlock: ^(id<STLayer> layer, NSUInteger idx, BOOL *stop) {\n\t\tNSDictionary *metadata = [self metadataForLayer: layer];\n\t\tNSArray *keysToKeep = [metadata.allKeys st_filter: ^BOOL(NSString *key) {\n\t\t\treturn [key isNotEqualTo: stateToRemove.UUID.UUIDString];\n\t\t}];\n\t\t[self setMedatada: [metadata dictionaryWithValuesForKeys: keysToKeep] forLayer: layer];\n\t}];\n}\n\n- (void)applyState: (STStateDescription *)state\n{\n\tNSParameterAssert([self.allStates containsObject: state]);\n\n\t[[self children] enumerateObjectsUsingBlock: ^(id<STLayer> layer, NSUInteger idx, BOOL *stop) {\n\t\tNSDictionary *metadata = [self metadataForLayer: layer][state.UUID.UUIDString];\n\t\tif (metadata.count == 0) {\n\t\t\treturn;\n\t\t}\n\t\tSTLayerState *layerState = [[STLayerState alloc] initWithDictionary: metadata];\n\t\tNSAssert(layerState != nil, @\"Requested state values are missing from layer's metadata\");\n\t\t[STLayerStateApplier apply: layerState toLayer: layer];\n\t}];\n\n\tself.currentState = state;\n}\n\n- (void)updateCurrentState\n{\n\tSTStateDescription *state = self.currentState;\n\tNSParameterAssert(self.currentState != nil);\n\n\t[[self children] enumerateObjectsUsingBlock: ^(id<STLayer> layer, NSUInteger idx, BOOL *stop) {\n\t\tNSMutableDictionary *newMetadata = [[self metadataForLayer: layer] mutableCopy];\n\t\tSTLayerState *layerState = [STLayerStateFetcher fetchStateFromLayer: layer];\n\t\tnewMetadata[state.UUID.UUIDString] = [layerState dictionaryRepresentation];\n\t\t[self setMedatada: newMetadata forLayer: layer];\n\t}];\n}\n\n- (void)copyState: (STStateDescription *)source toState: (STStateDescription *)destination\n{\n\tNSParameterAssert([self.allStates containsObject: source]);\n\tNSParameterAssert([self.allStates containsObject: destination]);\n\n\t// Copy all of the child layers metadata from `source` state to `destination`\n\t[[self children] enumerateObjectsUsingBlock: ^(id<STLayer> layer, NSUInteger idx, BOOL *stop) {\n\t\tNSMutableDictionary *newMetadata = [[self metadataForLayer: layer] mutableCopy];\n\t\tNSAssert(newMetadata[source.UUID.UUIDString], @\"The source state metadata doesn't exists on layer %@\", layer);\n\t\tnewMetadata[destination.UUID.UUIDString] = newMetadata[source.UUID.UUIDString];\n\t\t[self setMedatada: newMetadata forLayer: layer];\n\t}];\n}\n\n- (void)insertNewState: (STStateDescription *)newState\n{\n\tNSParameterAssert(![self.allStates containsObject: newState]);\n\n\t// 1) insert this new state into the artboard's registry\n\tNSArray *oldRawStates = [self artboardStatesData];\n\t[self setArtboardStatesData: [oldRawStates arrayByAddingObject: newState.dictionaryRepresentation]];\n\n\t// 2) update all child layer with the new state: it will be a current layer snapshot\n\t[[self children] enumerateObjectsUsingBlock: ^(id<STLayer> layer, NSUInteger idx, BOOL *stop) {\n\t\t// TODO: this is the same code as in -updateCurrentState (just replace state <-> newState)\n\t\tNSMutableDictionary *newMetadata = [[self metadataForLayer: layer] mutableCopy];\n\t\tSTLayerState *layerState = [STLayerStateFetcher fetchStateFromLayer: layer];\n\t\tnewMetadata[newState.UUID.UUIDString] = [layerState dictionaryRepresentation];\n\t\t[self setMedatada: newMetadata forLayer: layer];\n\t}];\n\n\tif (!self.currentState) {\n\t\t[self setCurrentState: newState];\n\t}\n}\n\n- (STStateDescription *)updateName: (NSString *)newName forState: (STStateDescription *)oldState\n{\n\tNSParameterAssert([self.allStates containsObject: oldState]);\n\n\tSTStateDescription *newState = [oldState stateByAlteringTitle: newName];\n\tNSMutableArray *stateRegistry = [[self artboardStatesData] mutableCopy];\n\tNSUInteger idx = [stateRegistry indexOfObject: oldState.dictionaryRepresentation];\n\tNSAssert(idx != NSNotFound, @\"Could not find the given state\");\n\t// Modify a states registry\n\t[stateRegistry replaceObjectAtIndex: idx withObject: newState.dictionaryRepresentation];\n\t[self setArtboardStatesData: stateRegistry];\n    // What if we rename the default state?\n    if ([oldState isEqual: self.defaultState]) {\n        [self updateDefaultState: newState];\n    }\n\t// Also update the current state if needed\n\tif ([oldState isEqual: self.currentState]) {\n\t\t[self setCurrentState: newState];\n\t}\n\n\treturn newState;\n}\n\n- (void)reorderStates: (NSArray <STStateDescription *> *)allStatesInNewOrder\n{\n\tNSAssert([[NSSet setWithArray: self.allStates] isEqualToSet: [NSSet setWithArray: allStatesInNewOrder]],\n\t\t\t @\"Invalid argument\");\n\t[self setAllStates: allStatesInNewOrder];\n}\n\n#pragma mark - Artboard State Metadata\n\n- (NSArray <STStateDescription *> *)allStates\n{\n\treturn [[self artboardStatesData] st_map: ^STStateDescription *(NSDictionary *model) {\n\t\treturn [[STStateDescription alloc] initWithDictionary: model];\n\t}];\n}\n\n- (STStateDescription *)currentState\n{\n\tNSDictionary *currentStateData = [self artboardCurrentStateData];\n\tif (currentStateData.count == 0) {\n\t\treturn nil;\n\t}\n\treturn [[STStateDescription alloc] initWithDictionary: currentStateData];\n}\n\n- (STStateDescription *)defaultState\n{\n\tNSDictionary *defaultStateDictionary = [self artboardDefaultStateData];\n\tif (defaultStateDictionary.count == 0) {\n\t\treturn nil;\n\t}\n\treturn [[STStateDescription alloc] initWithDictionary: defaultStateDictionary];\n}\n\n#pragma mark - Internal Metadata\n\n- (void)setAllStates: (NSArray<STStateDescription *> *)allStates\n{\n\tNSArray *rawStates = [allStates st_map: ^NSDictionary *(STStateDescription *state) {\n\t\treturn [state dictionaryRepresentation];\n\t}];\n\t[self setArtboardStatesData: rawStates];\n}\n\n- (void)setCurrentState: (STStateDescription *)newCurrentState\n{\n\tNSParameterAssert([self.allStates containsObject: newCurrentState]);\n\tNSDictionary *state = [newCurrentState dictionaryRepresentation];\n\t[self setArtboardCurrentStateData: state];\n}\n\n- (void)setDefaultState: (STStateDescription *)defaultState\n{\n\tNSParameterAssert(self.defaultState == nil);\n\tNSDictionary *stateDictionary = [defaultState dictionaryRepresentation];\n\t[self setArtboardDefaultStateData: stateDictionary];\n}\n\n- (void)updateDefaultState: (STStateDescription *)defaultState\n{\n    NSDictionary *stateDictionary = [defaultState dictionaryRepresentation];\n    [self setArtboardDefaultStateData: stateDictionary];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STTableCellView.h",
    "content": "// STTableCellView.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n\n@import Cocoa;\n\n#import \"STUpdateButton.h\"\n\n@class STTableCellView;\n\n@protocol STTableCellViewDelegate <NSObject>\n@required\n- (BOOL)cellViewRepresentsCurrentItem: (STTableCellView *)cellView;\n- (BOOL)isSingleRowSelected;\n@end\n\n/// A cell view that sets custom text field colors depending on whether it represents the current\n/// state model or not\n@interface STTableCellView : NSTableCellView\n\n@property (weak) id <STTableCellViewDelegate> delegate;\n@property (weak) IBOutlet STUpdateButton *updateButton;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STTableCellView.m",
    "content": "// STTableCellView.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n\n#import \"STColorFactory.h\"\n#import \"STTableCellView.h\"\n\n@implementation STTableCellView\n\n- (void)setBackgroundStyle: (NSBackgroundStyle)backgroundStyle\n{\n\t[super setBackgroundStyle: backgroundStyle];\n\n\tif (backgroundStyle == NSBackgroundStyleLight) {\n\t\tself.textField.textColor = [STColorFactory tableViewCellTextRegularColor];\n\t} else {\n\t\tBOOL singleSelection = [self.delegate isSingleRowSelected];\n\t\t\n\t\tif (singleSelection || [self.delegate cellViewRepresentsCurrentItem: self]) {\n\t\t\tself.textField.textColor = [STColorFactory tableViewCellTextSelectedColorWithAlpha: 1.0f];\n\t\t} else {\n\t\t\tself.textField.textColor = [STColorFactory tableViewCellTextSelectedColorWithAlpha: 0.5f];\n\t\t}\n\t}\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STTableRowView.h",
    "content": "// STTableRowView.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Cocoa;\n\n/// A row view that draws custom background and selection rectangles\n@interface STTableRowView : NSTableRowView\n\n@property (readonly, weak) NSTableView *tableView;\n\n- (instancetype)initWithTableView: (NSTableView *)containingTableView;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STTableRowView.m",
    "content": "// STTableRowView.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STColorFactory.h\"\n#import \"STTableRowView.h\"\n#import \"STTableCellView.h\"\n\n@interface STTableRowView()\n@property (readwrite, weak) NSTableView *tableView;\n@end\n\n@implementation STTableRowView\n\n- (instancetype)initWithTableView: (NSTableView *)containingTableView\n{\n\tif ((self = [super initWithFrame: NSZeroRect])) {\n\t\t_tableView = containingTableView;\n\t}\n\treturn self;\n}\n\n- (void)drawBackgroundInRect: (NSRect)dirtyRect\n{\n\t[super drawBackgroundInRect: dirtyRect];\n\tNSInteger row = [self.tableView rowForView: self];\n\tif (row % 2 == 0) {\n\t\t[[STColorFactory mainTableViewRowColor] setFill];\n\t} else {\n\t\t[[STColorFactory secondaryTableViewRowColor] setFill];\n\t}\n\tNSBezierPath *path = [NSBezierPath bezierPathWithRect: dirtyRect];\n\t[path fill];\n}\n\n- (void)drawSelectionInRect: (NSRect)dirtyRect\n{\n\t[super drawBackgroundInRect: dirtyRect];\n\tif (self.emphasized) {\n\t\t[[STColorFactory selectedTableViewRowColor] setFill];\n\t} else {\n\t\t[[STColorFactory selectedInactiveTableViewRowColor] setFill];\n\t}\n\tNSBezierPath *path = [NSBezierPath bezierPathWithRect: dirtyRect];\n\t[path fill];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STTableView.h",
    "content": "// STTableView.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Cocoa;\n\n/// A table view that disables navigation with arrow keys and draws a custom background\n@interface STTableView : NSTableView\n@end\n"
  },
  {
    "path": "Plugin/States/STTableView.m",
    "content": "// STTableView.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n\n#import \"STColorFactory.h\"\n#import \"STTableView.h\"\n\n@implementation STTableView\n\n- (void)keyDown: (NSEvent *)theEvent\n{\n\tNSString *characters = [theEvent charactersIgnoringModifiers];\n\tunichar code = [characters characterAtIndex: 0];\n\t// Disable arrow keys navigation\n\tswitch (code) {\n\t\tcase NSUpArrowFunctionKey:\n\t\tcase NSDownArrowFunctionKey:\n\t\tcase NSLeftArrowFunctionKey:\n\t\tcase NSRightArrowFunctionKey:\n\t\t\treturn;\n\t\tdefault:\n\t\t\t[super keyDown: theEvent];\n\t}\n}\n\n- (void)drawBackgroundInClipRect: (NSRect)clipRect\n{\n\t[super drawBackgroundInClipRect: clipRect];\n\n\t[[STColorFactory tableViewBackgroundColor] setFill];\n\tNSBezierPath *path = [NSBezierPath bezierPathWithRect: clipRect];\n\t[path fill];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STTextField.h",
    "content": "// STTextField.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n\n@import Cocoa;\n\n@protocol STTextFieldFirstResponderDelegate <NSObject>\n@optional\n- (void)textFieldBecomeFirstResponder: (NSTextField *)textField;\n@end\n\n/// A text field that notifies its delegate that it has became firt responder\n@interface STTextField : NSTextField\n\n@property (weak) id <STTextFieldFirstResponderDelegate> firstResponderDelegate;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STTextField.m",
    "content": "// STTextField.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STColorFactory.h\"\n#import \"STTextField.h\"\n\n@implementation STTextField\n\n- (BOOL)becomeFirstResponder\n{\n\tdispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{\n\t\tself.textColor = [STColorFactory tableViewCellTextRegularColor];\n\t});\n\n\tBOOL result = [super becomeFirstResponder];\n\tif (result && [self.delegate respondsToSelector: @selector(textFieldBecomeFirstResponder:)]) {\n\t\t[self.firstResponderDelegate textFieldBecomeFirstResponder: self];\n\t}\n\treturn result;\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STUpdateButton.h",
    "content": "// STUpdateButton.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Cocoa;\n\ntypedef void (^STUpdateButtonAnimationCompletion)(void);\n\n/// A simple button that may rotate its image clockwise\n@interface STUpdateButton : NSButton\n\n- (void)spinWithCompletion: (STUpdateButtonAnimationCompletion)completion;\n\n@end\n"
  },
  {
    "path": "Plugin/States/STUpdateButton.m",
    "content": "// STUpdateButton.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import QuartzCore;\n\n#import \"STUpdateButton.h\"\n\n@interface STUpdateButton()\n{\n\tSTUpdateButtonAnimationCompletion _completion;\n}\n@end\n\n@implementation STUpdateButton\n\n- (instancetype)init\n{\n\tif ((self = [super init])) {\n\t\tself.wantsLayer = YES;\n\t}\n\treturn self;\n}\n\n\n- (void)spinWithCompletion: (STUpdateButtonAnimationCompletion)completion\n{\n\tif (!CGPointEqualToPoint(self.layer.anchorPoint, CGPointMake(0.5, 0.5))) {\n\t\t[self fixAnchorPoint];\n\t}\n\t// Rotate 360° clockwise\n\tCABasicAnimation *spinningAnimation = [CABasicAnimation animationWithKeyPath: @\"transform.rotation\"];\n\tspinningAnimation.fromValue = @(0.0f);\n\tspinningAnimation.toValue = @(-2 * M_PI);\n\tspinningAnimation.duration = 0.5f;\n\tspinningAnimation.delegate = self;\n\t_completion = (__bridge STUpdateButtonAnimationCompletion)(_Block_copy((__bridge const void *)(completion)));\n\t[self.layer addAnimation: spinningAnimation forKey: nil];\n}\n\n- (void)animationDidStop: (CAAnimation *)animation finished: (BOOL)flag\n{\n\tif (_completion) {\n\t\t_completion();\n\t\t_Block_release((__bridge const void *)(_completion));\n\t}\n}\n\n- (void)fixAnchorPoint\n{\n\tCGRect frame = self.layer.frame;\n\tCGPoint center = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));\n\tself.layer.position = center;\n\tself.layer.anchorPoint = CGPointMake(0.5, 0.5);\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/STWindow.h",
    "content": "// STWindow.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Cocoa;\n\n/// A panel which is movable by its background\n@interface STWindow : NSPanel\n@end\n"
  },
  {
    "path": "Plugin/States/STWindow.m",
    "content": "// STWindow.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STWindow.h\"\n\n@implementation STWindow\n\n- (BOOL)canBecomeKeyWindow\n{\n\treturn YES;\n}\n\n- (BOOL)isMovableByWindowBackground\n{\n\treturn YES;\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesController+ContextMenu.h",
    "content": "// StatesController+ContextMenu.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"StatesController.h\"\n\n/// A category that builds a context menu for selected rows\n@interface StatesController (ContextMenu) <NSMenuDelegate>\n\n- (void)menuNeedsUpdate: (NSMenu *)menu;\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesController+ContextMenu.m",
    "content": "// StatesController+ContextMenu.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STStateDescription.h\"\n#import \"STStatefulArtboard.h\"\n#import \"StatesController+ContextMenu.h\"\n\n@implementation StatesController (ContextMenu)\n\n- (void)menuNeedsUpdate: (NSMenu *)menu\n{\n\t[menu removeAllItems];\n\n\tNSInteger clickedRow = [self.tableView clickedRow];\n\tif (clickedRow < 0 || clickedRow >= _artboard.allStates.count) {\n\t\treturn;\n\t}\n\n\tNSArray <STStateDescription *>*selectedStates = [_artboard.allStates objectsAtIndexes:\n\t\t\t\t\t\t\t\t\t\t\t\t\t [self.tableView selectedRowIndexes]];\n\tif (selectedStates.count == 0) {\n\t\treturn;\n\t}\n\n\tSTStateDescription *clickedState = _artboard.allStates[clickedRow];\n\t// We're clicking an a row that isn't part of current selection: show a menu just for this one row\n\tif (![selectedStates containsObject: clickedState]) {\n\t\tselectedStates = @[clickedState];\n\t}\n\n\t// TODO?: add support for updating non-current states as well. Need to figure out\n\t// when \"updating\" them means though. Maybe just rewriting them to reflect current artboard properties?\n\tif (selectedStates.count == 1 && [clickedState isEqualTo: _artboard.currentState]) {\n\t\t[menu addItem: [self updateCurrentStateMenuItem]];\n\t}\n\n\t[menu addItem: [self duplicateMenuItemForStates: selectedStates]];\n\t[menu addItem: [NSMenuItem separatorItem]];\n\t[menu addItem: [self createPageMenuItemForStates: selectedStates]];\n\tif (selectedStates.count > 1 || [selectedStates.firstObject isNotEqualTo: _artboard.defaultState]) {\n\t\t[menu addItem: [NSMenuItem separatorItem]];\n\t\t[menu addItem: [self deleteMenuItemForStates: selectedStates]];\n\t}\n}\n\n#pragma mark Menu Items\n\n- (NSMenuItem *)updateCurrentStateMenuItem\n{\n\tNSMenuItem *item = [[NSMenuItem alloc] initWithTitle: @\"Update\"\n\t\t\t\t\t\t\t\t\t\t\t\t  action: @selector(updateCurrentState:)\n\t\t\t\t\t\t\t\t\t\t   keyEquivalent: @\"\"];\n\titem.target = self;\n\treturn item;\n}\n\n- (NSMenuItem *)duplicateMenuItemForStates: (NSArray <STStateDescription *> *)subjects\n{\n\tNSMenuItem *item = [[NSMenuItem alloc] initWithTitle: @\"Duplicate\"\n\t\t\t\t\t\t\t\t\t\t\t\t  action: @selector(duplicateStates:)\n\t\t\t\t\t\t\t\t\t\t   keyEquivalent: @\"\"];\n\titem.target = self;\n\titem.representedObject = subjects;\n\treturn item;\n}\n\n- (NSMenuItem *)createPageMenuItemForStates: (NSArray <STStateDescription *> *)subjects\n{\n\tNSMenuItem *item = [[NSMenuItem alloc] initWithTitle: @\"Create Page\"\n\t\t\t\t\t\t\t\t\t\t\t\t  action: @selector(createPageFromStates:)\n\t\t\t\t\t\t\t\t\t\t   keyEquivalent: @\"\"];\n\titem.target = self;\n\titem.representedObject = subjects;\n\treturn item;\n}\n\n- (NSMenuItem *)deleteMenuItemForStates: (NSArray <STStateDescription *> *)subjects\n{\n\tNSMenuItem *item = [[NSMenuItem alloc] initWithTitle: @\"Delete\"\n\t\t\t\t\t\t\t\t\t\t\t\t  action: @selector(deleteStates:)\n\t\t\t\t\t\t\t\t\t\t   keyEquivalent: @\"\"];\n\titem.target = self;\n\titem.representedObject = subjects;\n\treturn item;\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesController+Decisions.h",
    "content": "// StatesController+Decisions.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"StatesController.h\"\n\n@class STStateDescription;\n\n/// A category that asks user's confirmation for (likely) destructive events\n@interface StatesController (Decisions)\n\n- (BOOL)shouldSwitchToState: (STStateDescription *)newState fromState: (STStateDescription *)oldState;\n\n- (BOOL)shoulRemoveStates: (NSArray <STStateDescription *> *)states;\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesController+Decisions.m",
    "content": "// StatesController+Decisions.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STStateDescription.h\"\n#import \"STStatefulArtboard.h\"\n#import \"NSArray+HigherOrder.h\"\n#import \"StatesController+Decisions.h\"\n\n#define kNumberOfStatesToShowInDeleteAlert (10)\n\n@implementation StatesController (Decisions)\n\n- (BOOL)shouldSwitchToState: (STStateDescription *)newState fromState: (STStateDescription *)oldState\n{\n\t// If there aren't any changes then the switch is safe\n\tif ([_artboard conformsToState: oldState]) {\n\t\treturn YES;\n\t}\n\n\t// When we're switching to the same state it means we're to reset all of the changes\n\t// made to this state\n\tif ([oldState isEqual: newState]) {\n\t\tNSAlert *alert = [[NSAlert alloc] init];\n\t\talert.messageText = [NSString stringWithFormat:\n\t\t\t\t\t\t\t @\"Do you want to revert any changes made to state \\\"%@\\\"?\", oldState.title];\n\t\t[alert addButtonWithTitle: @\"Revert changes\"];\n\t\t[alert addButtonWithTitle: @\"Cancel\"];\n\n\t\tNSModalResponse response = [alert runModal];\n\t\tswitch (response) {\n\t\t\tcase NSAlertFirstButtonReturn:\n\t\t\t\t// \"Revert\": allow to re-apply this state\n\t\t\t\treturn YES;\n\t\t\tcase NSAlertSecondButtonReturn:\n\t\t\t\t// \"Cancel\": do nothing\n\t\t\t\treturn NO;\n\t\t\tdefault:\n\t\t\t\treturn NO;\n\t\t}\n\t} else {\n\t\t// Otherwise it's just a regular switch between different states\n\t\tNSAlert *alert = [[NSAlert alloc] init];\n\t\talert.messageText = [NSString stringWithFormat:\n\t\t\t\t\t\t\t @\"Update changes to state \\\"%@\\\" before switching to \\\"%@\\\"?\",\n\t\t\t\t\t\t\t oldState.title, newState.title];\n\t\t[alert addButtonWithTitle: @\"Update\"];\n\t\t[alert addButtonWithTitle: @\"Cancel\"];\n\t\t[alert addButtonWithTitle: @\"Don’t Update\"];\n\n\t\tNSModalResponse response = [alert runModal];\n\t\tswitch (response) {\n\t\t\tcase NSAlertFirstButtonReturn:\n\t\t\t\t// \"Update\": update the current state and switch to a new one\n\t\t\t\t[_artboard updateCurrentState];\n\t\t\t\treturn YES;\n\t\t\tcase NSAlertSecondButtonReturn:\n\t\t\t\t// \"Cancel\": do nothing\n\t\t\t\treturn NO;\n\t\t\tcase NSAlertThirdButtonReturn:\n\t\t\t\t// \"Do not update\": so to say, just switch to the new state\n\t\t\t\treturn YES;\n\t\t\tdefault:\n\t\t\t\treturn NO;\n\t\t}\n\t}\n}\n\n- (BOOL)shoulRemoveStates: (NSArray <STStateDescription *> *)states\n{\n\tNSParameterAssert(states.count > 0);\n\n\tNSArray <NSString *>*titles = [states st_map: ^NSString *(STStateDescription *state) {\n\t\treturn [NSString stringWithFormat: @\"\\t• %@\", state.title];\n\t}];\n\n\tif (titles.count > kNumberOfStatesToShowInDeleteAlert) {\n\t\tNSInteger total = titles.count;\n\t\ttitles = [titles subarrayWithRange: NSMakeRange(0, kNumberOfStatesToShowInDeleteAlert)];\n\t\ttitles = [titles arrayByAddingObject: [NSString stringWithFormat: @\"\\t(and %ld more)\",\n\t\t\t\t\t\t\t\t\t\t\t   total-kNumberOfStatesToShowInDeleteAlert]];\n\t}\n\n\tNSAlert *alert = [[NSAlert alloc] init];\n\tif (titles.count == 1) {\n\t\talert.messageText = [NSString stringWithFormat:\n\t\t\t\t\t\t\t @\"Do you want to delete state \\\"%@\\\"?\", states.firstObject.title];\n\t} else {\n\t\talert.messageText = [NSString stringWithFormat:\n\t\t\t\t\t\t\t @\"Do you want to delete the following states:\\n%@\",\n\t\t\t\t\t\t\t [titles componentsJoinedByString: @\"\\n\"]];\n\t}\n\n\talert.informativeText = @\"All of the settings on this state will also be removed.\";\n\t[alert addButtonWithTitle: @\"Cancel\"];\n\t[alert addButtonWithTitle: @\"Delete\"];\n\n\tNSModalResponse response = [alert runModal];\n\tswitch (response) {\n\t\tcase NSAlertFirstButtonReturn:\n\t\t\t// \"Cancel\"\n\t\t\treturn NO;\n\t\tcase NSAlertSecondButtonReturn:\n\t\t\t// \"Delete\"\n\t\t\treturn YES;\n\t\tdefault:\n\t\t\treturn NO;\n\t}\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesController+DragNDrop.h",
    "content": "// StatesController+DragNDrop.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"StatesController.h\"\n\n@interface StatesController (DragNDrop)\n\n- (void)registerTableViewForDragNDrop;\n\n// This category also implements the following NSTableViewDataSources methods:\n\n- (BOOL)tableView: (NSTableView *)tableView writeRowsWithIndexes: (NSIndexSet *)rowIndexes toPasteboard: (NSPasteboard *)pboard;\n\n- (NSDragOperation)tableView: (NSTableView *)tableView validateDrop: (id <NSDraggingInfo>)info proposedRow: (NSInteger)row proposedDropOperation: (NSTableViewDropOperation)dropOperation;\n\n- (BOOL)tableView: (NSTableView *)tableView acceptDrop: (id <NSDraggingInfo>)info row: (NSInteger)row dropOperation: (NSTableViewDropOperation)dropOperation;\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesController+DragNDrop.m",
    "content": "// StatesController+DragNDrop.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STStatefulArtboard.h\"\n#import \"StatesController+DragNDrop.h\"\n\nNSString * const kStatesControllerDraggedType = @\"StatesControllerDraggedType\";\n\n@implementation StatesController (DragNDrop)\n\n- (void)registerTableViewForDragNDrop;\n{\n\t[self.tableView registerForDraggedTypes: @[kStatesControllerDraggedType]];\n}\n\n- (BOOL)tableView: (NSTableView *)tableView writeRowsWithIndexes: (NSIndexSet *)rowIndexes toPasteboard: (NSPasteboard *)pboard\n{\n\tNSData *indexesData = [NSKeyedArchiver archivedDataWithRootObject: rowIndexes];\n\t[pboard declareTypes: @[kStatesControllerDraggedType] owner: self];\n\t[pboard setData: indexesData forType: kStatesControllerDraggedType];\n\treturn YES;\n}\n\n- (NSDragOperation)tableView: (NSTableView *)tableView validateDrop: (id <NSDraggingInfo>)info proposedRow: (NSInteger)row proposedDropOperation: (NSTableViewDropOperation)dropOperation\n{\n\tif (dropOperation == NSTableViewDropAbove) {\n\t\t[info setAnimatesToDestination: YES];\n\t\treturn NSDragOperationMove;\n\t}\n\treturn NSDragOperationNone;\n}\n\n- (BOOL)tableView: (NSTableView *)tableView acceptDrop: (id <NSDraggingInfo>)info row: (NSInteger)row dropOperation: (NSTableViewDropOperation)dropOperation\n{\n\tNSData *data = [[info draggingPasteboard] dataForType: kStatesControllerDraggedType];\n\tNSIndexSet *sourceIndexes = [NSKeyedUnarchiver unarchiveObjectWithData: data];\n\t//\n\t// FIXME: support dragging multiple items\n\t//\n\tNSUInteger destination = MIN(MAX(row, 0), _artboard.allStates.count-1);\n\tNSMutableArray *states = [_artboard.allStates mutableCopy];\n\tNSUInteger source = sourceIndexes.firstIndex;\n\n\t// 1) model updates\n\tid draggedState = [states objectAtIndex: source];\n\t[states removeObjectAtIndex: source];\n\t[states insertObject: draggedState atIndex: destination];\n\t[_artboard reorderStates: states];\n\t// 2) table view updates\n\t[tableView moveRowAtIndex: source toIndex: destination];\n\n\treturn YES;\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesController+Naming.h",
    "content": "// StatesController+Naming.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"StatesController.h\"\n@class STStateDescription;\n\n/// Naming things is the second hard thing in programming\n@interface StatesController (Naming)\n\n/// Enumerates names such as \"State\", \"State 1\", \"State 2\" etc and returns the first available one\n- (NSString *)newStateNameInStates: (NSArray <STStateDescription *> *)existingStates;\n\n/// Returns a name for a new page containing shapshots of the given states\n- (NSString *)pageNameForStates: (NSArray <STStateDescription *> *)states sourcePage: (id <STPage>)sourcePage;\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesController+Naming.m",
    "content": "// StatesController+Naming.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STPage.h\"\n#import \"STStateDescription.h\"\n#import \"NSArray+HigherOrder.h\"\n#import \"StatesController+Naming.h\"\n\n@implementation StatesController (Naming)\n\n/// Enumerates names such as \"State\", \"State 1\", \"State 2\" etc and returns the first available one\n- (NSString *)newStateNameInStates: (NSArray <STStateDescription *> *)existingStates\n{\n\tstatic NSString *template = @\"State\";\n\tNSSet *matchedNames = [NSSet setWithArray:\n\t\t\t\t\t\t   [existingStates st_map: ^NSString *(STStateDescription *state) {\n\t\treturn state.title;\n\t}]];\n\n\tNSInteger idx = 1;\n\tNSString *newName = template;\n\twhile ([matchedNames containsObject: newName]) {\n\t\tnewName = [NSString stringWithFormat: @\"%@ %ld\", template, idx++];\n\t}\n\n\treturn newName;\n}\n\n- (NSString *)pageNameForStates: (NSArray <STStateDescription *> *)states sourcePage: (id <STPage>)sourcePage;\n{\n\tNSString *titles = [[states st_map: ^NSString *(STStateDescription *state) {\n\t\treturn state.title;\n\t}] componentsJoinedByString: @\", \"];\n\n\treturn [NSString stringWithFormat: @\"%@ :: %@ [Snapshots for %@]\",\n\t\t\tsourcePage.name, [sourcePage currentArtboard].name, titles];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesController.h",
    "content": "// StatesController.h\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import Cocoa;\n\n@class STStatefulArtboard;\n@class STUpdateButton;\n@class STTableCellView;\n\n/// So here you are, looking for a challenge. This one is responsible for managing the states\n/// table view and responding to user's actions by modifing current artboard.\n///\n/// It's huge and ungly. But I tried my best to make this controller as stateless (such irony!) as\n/// possible so at least one could easily refactor different bits into separate classes 🌟\n@interface StatesController : NSWindowController\n<NSTableViewDelegate, NSTableViewDataSource, NSTextFieldDelegate>\n{\n@protected\n\tSTStatefulArtboard *_artboard;\n}\n@property (weak) IBOutlet NSTableView *tableView;\n@property (weak) IBOutlet STUpdateButton *addNewStateButton;\n@property (weak) IBOutlet NSView *placeholderView;\n\n+ (instancetype)defaultController;\n\n/// Creates a new state\n- (void)createNewState: (id)sender;\n/// Update the current state: make it reflect current artboard attributes\n- (void)updateCurrentState: (NSMenuItem *)sender;\n/// Create duplicates for all selected states\n- (void)duplicateStates: (NSMenuItem *)sender;\n/// Create a one page containing as many artboards as selected states: each of them will contain\n/// a snapshot of the current artboard in a corresponding state\n- (void)createPageFromStates: (NSMenuItem *)sender;\n/// Delete all selected states\n- (void)deleteStates: (NSMenuItem *)sender;\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesController.m",
    "content": "// StatesController.m\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n#import \"STPage.h\"\n#import \"STSketch.h\"\n#import \"STTextField.h\"\n#import \"STTableRowView.h\"\n#import \"STColorFactory.h\"\n#import \"STTableCellView.h\"\n#import \"NSArray+Indexes.h\"\n#import \"STStatefulArtboard.h\"\n#import \"NSArray+HigherOrder.h\"\n#import \"STStatefulArtboard+Snapshots.h\"\n#import \"StatesController.h\"\n#import \"StatesController+Naming.h\"\n#import \"StatesController+Decisions.h\"\n#import \"StatesController+DragNDrop.h\"\n#import \"StatesController+ContextMenu.h\"\n\n@interface StatesController()\n<SketchNotificationsListener, STTextFieldFirstResponderDelegate, STTableCellViewDelegate>\n@end\n\n@implementation StatesController\n\n+ (instancetype)defaultController\n{\n\tstatic StatesController *controller = nil;\n\tstatic dispatch_once_t onceToken;\n\tdispatch_once(&onceToken, ^{\n\t\tcontroller = [[StatesController alloc] init];\n\t\t[[STSketch notificationObserver] addListener: controller];\n\t});\n\treturn controller;\n}\n\n- (NSString *)windowNibName\n{\n\treturn @\"StatesWindow\";\n}\n\n- (void)awakeFromNib\n{\n\t[(NSPanel *)self.window setWorksWhenModal: NO];\n\t[(NSPanel *)self.window setFloatingPanel: YES];\n\n\t/// NOTE: these two images are from Sketch\n\tself.addNewStateButton.image = [NSImage imageNamed: @\"pages_add\"];\n\tself.addNewStateButton.alternateImage = [NSImage imageNamed: @\"pages_add_pressed\"];\n\tself.addNewStateButton.toolTip = @\"Add a new state which will reflect the current artboard parameters\";\n\n\tself.tableView.menu = [NSMenu new];\n\tself.tableView.menu.delegate = self;\n\tself.tableView.action = @selector(singleClicked:);\n\tself.tableView.doubleAction = @selector(doubleClicked:);\n\t[self registerTableViewForDragNDrop];\n\n\t[self resetArtboard: [STSketch currentArtboard]];\n}\n\n- (void)resetArtboard: (STStatefulArtboard *)artboard\n{\n\t_artboard = artboard;\n\t[self.tableView reloadData];\n\n\tif (!_artboard) {\n\t\tself.placeholderView.hidden = NO;\n\t\tself.addNewStateButton.enabled = NO;\n\t\treturn;\n\t}\n\n\tself.placeholderView.hidden = YES;\n\tself.addNewStateButton.enabled = YES;\n\n\t// Pre-select the current state (if any)\n\tNSUInteger currentStateIndex = [_artboard.allStates indexOfObject: _artboard.currentState];\n\tif (currentStateIndex != NSNotFound) {\n\t\t[self.tableView selectRowIndexes: [NSIndexSet indexSetWithIndex: currentStateIndex]\n\t\t\t\t\tbyExtendingSelection: NO];\n\t}\n}\n\n#pragma mark - SketchNotificationsListener\n\n- (void)currentArtboardDidChange\n{\n\t[self resetArtboard: [STSketch currentArtboard]];\n}\n\n- (void)currentArtboardUnselected\n{\n\t[self resetArtboard: nil];\n}\n\n- (void)currentDocumentUpdated\n{\n\tif (!_artboard.currentState) {\n\t\treturn;\n\t}\n\t[self resetDirtyMarkOnStates];\n}\n\n#pragma mark - Dirty States\n\n- (void)resetDirtyMarkOnStates\n{\n\t// Show or hide an update button depending on a situation\n\t[_artboard.allStates enumerateObjectsUsingBlock: ^(STStateDescription *state, NSUInteger idx, BOOL *stop) {\n\t\tSTTableCellView *cell = [self.tableView viewAtColumn: 0 row: idx makeIfNecessary: NO];\n\t\tif ([state isEqualTo: _artboard.currentState] && ([self.tableView editedRow] != idx)) {\n\t\t\tcell.updateButton.animator.hidden = [_artboard conformsToState: state];\n\t\t} else {\n\t\t\tcell.updateButton.animator.hidden = YES;\n\t\t}\n\t}];\n}\n\n#pragma mark - STTableCellViewDelegate\n\n- (BOOL)cellViewRepresentsCurrentItem: (STTableCellView *)cellView\n{\n\tNSInteger idx = [_artboard.allStates indexOfObject: _artboard.currentState];\n\tif (!_artboard || idx == NSNotFound) {\n\t\treturn NO;\n\t}\n\treturn cellView == [self.tableView viewAtColumn: 0 row: idx makeIfNecessary: NO];\n}\n\n- (BOOL)isSingleRowSelected\n{\n\treturn [self.tableView selectedRowIndexes].count == 1;\n}\n\n#pragma mark - User Actions\n\n- (IBAction)createNewState: (id)sender\n{\n\tNSString *newStateName = [self newStateNameInStates: _artboard.allStates];\n\tSTStateDescription *state = [[STStateDescription alloc] initWithTitle: newStateName];\n\n\t[_artboard insertNewState: state];\n\n\t// Update the table view\n\tNSInteger newIndex = _artboard.allStates.count-1;\n\t[self.tableView insertRowsAtIndexes: [NSIndexSet indexSetWithIndex: newIndex]\n\t\t\t\t\t\t  withAnimation: NSTableViewAnimationEffectFade];\n\t// No need to ask user about switching, since the settings are already saved in this new state\n\t[self.tableView selectRowIndexes: [NSIndexSet indexSetWithIndex: newIndex] byExtendingSelection: NO];\n\t// HACK: we avoid re-apply the same artboard properties again which can take a lot of time on big\n\t// artboards by setting the current state directly instead of calling -applyState:.\n\t// This is a workaround and should be removed as soon as we find a proper solution to our\n\t// performance issues\n\t[_artboard setCurrentState: state];\n\t[self resetDirtyMarkOnStates];\n\t// Move focus to the row to allow user to immdiately change the title value\n\t[self.tableView editColumn: 0 row: newIndex withEvent: nil select: YES];\n}\n\n- (IBAction)updateCurrentState: (NSMenuItem *)sender\n{\n\tNSInteger idx = [_artboard.allStates indexOfObject: _artboard.currentState];\n\tNSParameterAssert(idx != NSNotFound);\n\n\tSTTableCellView *cell = [self.tableView viewAtColumn: 0 row: idx makeIfNecessary: NO];\n\n\t// Animations first!\n\t__block BOOL animationCompleted = NO;\n\t[cell.updateButton spinWithCompletion: ^{\n\t\t[self resetDirtyMarkOnStates];\n\t\tanimationCompleted = YES;\n\t}];\n\t// Then actually update the model\n\t[_artboard updateCurrentState];\n\t// Finally we double check that the update button may be hiden safely\n\tif (animationCompleted) {\n\t\t[self resetDirtyMarkOnStates];\n\t}\n}\n\n- (IBAction)duplicateStates: (NSMenuItem *)sender\n{\n\tNSArray <STStateDescription *> *originals = sender.representedObject;\n\tNSParameterAssert([originals isKindOfClass: [NSArray class]]);\n\t// Create a copy for every original state passed by sender\n\t[originals enumerateObjectsUsingBlock: ^(STStateDescription *state, NSUInteger idx, BOOL *stop) {\n\t\tNSString *duplicateTitle = [NSString stringWithFormat: @\"%@ copy\", state.title];\n\t\tSTStateDescription *duplicate = [[STStateDescription alloc] initWithTitle: duplicateTitle];\n\t\t[_artboard insertNewState: duplicate];\n\t\t[_artboard copyState: state toState: duplicate];\n\t}];\n\t// Update the table view to reveal this new states\n\tNSRange newStatesRange = NSMakeRange(_artboard.allStates.count-1, originals.count);\n\tNSIndexSet *newIndexes = [NSIndexSet indexSetWithIndexesInRange: newStatesRange];\n\t[self.tableView insertRowsAtIndexes: newIndexes\n\t\t\t\t\t\t  withAnimation: NSTableViewAnimationEffectFade];\n}\n\n- (void)createPageFromStates: (NSMenuItem *)sender\n{\n\tNSArray <STStateDescription *> *selectedStates = sender.representedObject;\n\tNSParameterAssert([selectedStates isKindOfClass: [NSArray class]]);\n\n\t// 1) Create a new page\n\tid <STPage> currentPage = [STSketch currentPage];\n\tid <STPage> newPage = [NSClassFromString(@\"MSPage\") page];\n\tNSAssert(newPage != nil, @\"+[MSPage page] returned nil. Is this method still available?\");\n\n\tnewPage.name = [self pageNameForStates: selectedStates sourcePage: currentPage];\n\t// XXX: MSPage's pageDelegate property doesn't exist since 3.9\n    if ([newPage respondsToSelector: @selector(pageDelegate)]) {\n\t\tnewPage.pageDelegate = currentPage.pageDelegate;\n    }\n\tnewPage.grid = currentPage.grid;\n\tnewPage.layout = currentPage.layout;\n\n\t// 2) for each selected state we create a \"snapshot\" artboard and copy it to this new page\n\tNSArray *artboards = [selectedStates st_map: ^id<STArtboard>(STStateDescription *state) {\n\t\treturn [_artboard snapshotForState: state];\n\t}];\n\t// 2.1) we want these artboards to be aligned in a line with a little space in between items\n\tCGFloat gap = 200.f;\n\t__block CGPoint location = CGPointZero;\n \t[artboards enumerateObjectsUsingBlock: ^(id <STArtboard> artboard, NSUInteger idx, BOOL *stop) {\n\t\tif (idx == 0) {\n\t\t\tlocation = [[artboard absoluteRect] absoluteRect].origin;\n\t\t}\n\t\t[[artboard absoluteRect] setX: location.x];\n\t\tlocation.x += [[artboard absoluteRect] absoluteRect].size.width + gap;\n\t}];\n\t[newPage addLayers: artboards];\n\n\t// 3) Insert this new page into the document\n\t[[[STSketch currentDocument] documentData] addPage: newPage];\n\t// 3.1) adjust scroll and zoom to match the source page\n\tnewPage.scrollOrigin = currentPage.scrollOrigin;\n\tnewPage.zoomValue = currentPage.zoomValue;\n\t// 3.2) mark this new page as current\n\t[STSketch currentDocument].currentPage = newPage;\n\n\t// 4) Select the first available artboard on a new page\n\tif (newPage.artboards.count > 0) {\n\t\t[[[STSketch currentDocument] documentData] deselectAllLayers];\n\t\t[newPage selectLayers: @[newPage.artboards.firstObject]];\n\t}\n}\n\n- (IBAction)deleteStates: (NSMenuItem *)sender\n{\n\tNSMutableArray <STStateDescription *> *statesToDelete = [sender.representedObject mutableCopy];\n\tNSParameterAssert([statesToDelete isKindOfClass: [NSArray class]]);\n\n\t// We can not remove the default state so just remove if from the proposed set of states\n\t[statesToDelete removeObject: _artboard.defaultState];\n\n\tif (![self shoulRemoveStates: statesToDelete]) {\n\t\treturn;\n\t}\n\tNSIndexSet *indexesToDelete = [_artboard.allStates st_indexesOfObjects: statesToDelete];\n\t// 1) remove states from data model\n\t[statesToDelete enumerateObjectsUsingBlock: ^(STStateDescription *state, NSUInteger idx, BOOL *stop) {\n\t\t[_artboard removeState: state];\n\t}];\n\t// 2) remove corresponding rows from table view\n\t[self.tableView removeRowsAtIndexes: indexesToDelete withAnimation: NSTableViewAnimationEffectFade];\n\t// 3) update table view selection\n\tNSInteger newCurrentState = [_artboard.allStates indexOfObject: _artboard.currentState];\n\tif (newCurrentState != NSNotFound) {\n\t\t[self.tableView selectRowIndexes: [NSIndexSet indexSetWithIndex: newCurrentState]\n\t\t\t\t\tbyExtendingSelection: NO];\n\t}\n}\n\n/// Single click switches current state\n- (void)singleClicked: (id)sender\n{\n\t// Ignore clicks when multiple rows are selected\n\tif ([self.tableView selectedRowIndexes].count > 1) {\n\t\treturn;\n\t}\n\n\tNSInteger row = [self.tableView clickedRow];\n\tif (row < 0 || row >= _artboard.allStates.count) {\n\t\treturn;\n\t}\n\tSTStateDescription *newState = _artboard.allStates[row];\n\tif (!newState) {\n\t\treturn;\n\t}\n\t// Clicking on the same state will drop any current changes so we ask user about it\n\tif ([newState isEqualTo: _artboard.currentState]) {\n\t\tif ([self shouldSwitchToState: _artboard.currentState fromState: _artboard.currentState]) {\n\t\t\t[_artboard applyState: newState];\n\t\t}\n\t\treturn;\n\t}\n\t// -tableView:shouldSelectRow: has been called already so we just check if the target row\n\t// is selected and apply the new state accordingly.\n\tif ([self.tableView isRowSelected: row]) {\n\t\t[_artboard applyState: newState];\n\t\t[self resetDirtyMarkOnStates];\n\t}\n}\n\n/// Double click makes a state title text fiels editable\n- (void)doubleClicked: (id)sender\n{\n\t// Ignore clicks when multiple rows are selected\n\tif ([self.tableView selectedRowIndexes].count > 1) {\n\t\treturn;\n\t}\n\n\tNSInteger row = [self.tableView clickedRow];\n\tif (row < 0 || row >= _artboard.allStates.count) {\n\t\treturn;\n\t}\n\t[self.tableView editColumn: 0 row: row withEvent: nil select: YES];\n}\n\n#pragma mark User Did Commit New State Title\n\n- (void)controlTextDidEndEditing: (NSNotification *)obj\n{\n\tNSTextView *editor = [obj.userInfo valueForKey: @\"NSFieldEditor\"];\n\tNSInteger updatedRow = [self.tableView rowForView: editor];\n\tif (updatedRow < 0 || updatedRow >= _artboard.allStates.count) {\n\t\treturn;\n\t}\n\n\tNSString *newTitle = [[editor string] stringByTrimmingCharactersInSet:\n\t\t\t\t\t\t  [NSCharacterSet whitespaceAndNewlineCharacterSet]];\n\t// We either commit the change or just reset the row if user input is invalid\n\tif (newTitle.length > 0) {\n\t\t[_artboard updateName: newTitle forState: _artboard.allStates[updatedRow]];\n\t} else {\n\t\t[self.tableView reloadDataForRowIndexes: [NSIndexSet indexSetWithIndex: updatedRow]\n\t\t\t\t\t\t\t\t  columnIndexes: [NSIndexSet indexSetWithIndex: 0]];\n\t}\n\t// Don't forget about the update button we've hidden\n\t[self resetDirtyMarkOnStates];\n}\n\n/// Hide an update button when a state title is being edited\n- (void)textFieldBecomeFirstResponder: (NSTextField *)textField\n{\n\tNSInteger row = [self.tableView rowForView: textField];\n\tif (row < 0 || row >= _artboard.allStates.count) {\n\t\treturn;\n\t}\n\tSTTableCellView *cell = [self.tableView viewAtColumn: 0 row: row makeIfNecessary:NO];\n\tcell.updateButton.hidden = YES;\n}\n\n#pragma mark - NSTableViewDataSource & NSTableViewDelegate\n\n- (NSInteger)numberOfRowsInTableView: (NSTableView *)tableView\n{\n\treturn _artboard.allStates.count;\n}\n\n- (NSView *)tableView: (NSTableView *)tableView viewForTableColumn: (NSTableColumn *)tableColumn row: (NSInteger)row\n{\n\tSTStateDescription *state = _artboard.allStates[row];\n\tif (!state) {\n\t\treturn nil;\n\t}\n\tSTTableCellView *cellView = [tableView makeViewWithIdentifier: @\"StateCell\" owner: nil];\n\tif (!cellView) {\n\t\treturn nil;\n\t}\n\tcellView.delegate = self;\n\t// Setup text field\n\tcellView.textField.stringValue = state.title;\n\tcellView.textField.delegate = self;\n\t((STTextField *)cellView.textField).firstResponderDelegate = self;\n\t// Setup update button\n\tcellView.updateButton.action = @selector(updateCurrentState:);\n\tcellView.updateButton.target = self;\n\t// Toggle update button's visibility\n\tif ([[tableView selectedRowIndexes] containsIndex: row]) {\n\t\tcellView.updateButton.hidden = [_artboard conformsToState: state];\n\t} else {\n\t\tcellView.updateButton.hidden = YES;\n\t}\n\treturn cellView;\n}\n\n#pragma mark Selection Filter\n\n- (NSIndexSet *)tableView: (NSTableView *)tableView selectionIndexesForProposedSelection: (NSIndexSet *)proposedSelectionIndexes\n{\n\t// Don't allow table view to reset selection automatically from multiple rows to \"nothing\". In\n\t// this case it will select the last row which may not represent the current state\n\tif ([tableView selectedRowIndexes].count > 1 && proposedSelectionIndexes.count == 0) {\n\t\tNSInteger currentRow = [_artboard.allStates indexOfObject: _artboard.currentState];\n\t\tif (currentRow != NSNotFound) {\n\t\t\treturn [NSIndexSet indexSetWithIndex: currentRow];\n\t\t} else {\n\t\t\treturn [NSIndexSet indexSet];\n\t\t}\n\t}\n\t// Redraw the already selected row when we're dropping multiselection to just this one row\n\tif ([tableView selectedRowIndexes].count > 1 && proposedSelectionIndexes.count == 1) {\n\t\tSTStateDescription *newState = _artboard.allStates[proposedSelectionIndexes.firstIndex];\n\t\tif (![self shouldSwitchToState: newState fromState: _artboard.currentState]) {\n\t\t\treturn [NSIndexSet indexSet];\n\t\t}\n\t\tdispatch_after(dispatch_time(DISPATCH_TIME_NOW,\n\t\t\t\t\t\t\t\t\t (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(),\n\t\t^{\n\t\t\t[self.tableView rowViewAtRow: proposedSelectionIndexes.firstIndex\n\t\t\t\t\t\t makeIfNecessary: NO].needsDisplay = YES;\n\t\t});\n\t\treturn proposedSelectionIndexes;\n\t}\n\n\t// Always allow to expand selection. Note that we don't switch states in this case\n\tif (proposedSelectionIndexes.count > 1) {\n\t\treturn proposedSelectionIndexes;\n\t}\n\t// Always allow initial selection\n\tif (self.tableView.selectedRowIndexes.count == 0) {\n\t\treturn proposedSelectionIndexes;\n\t}\n\t// Don't allow to drop selection from one row to zero\n\tif (proposedSelectionIndexes.count == 0) {\n\t\treturn [NSIndexSet indexSet];\n\t}\n\t// So we're switching from one state to another; ask user about this\n\tSTStateDescription *oldState = _artboard.allStates[tableView.selectedRowIndexes.firstIndex];\n\tSTStateDescription *newState = _artboard.allStates[proposedSelectionIndexes.firstIndex];\n\tif ([self shouldSwitchToState: newState fromState: oldState]) {\n\t\treturn proposedSelectionIndexes;\n\t}\n\n\treturn [NSIndexSet indexSet];\n}\n\n- (void)tableViewSelectionDidChange:(NSNotification *)notification\n{\n\t// Update cell views for current selection state (e.g. set text color, etc)\n\t[_artboard.allStates enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL * stop) {\n\t\tNSTableCellView *view = [self.tableView viewAtColumn: 0 row: idx makeIfNecessary: NO];\n\t\tview.backgroundStyle = view.backgroundStyle;\n\t}];\n}\n\n#pragma mark Row Coloring\n\n- (NSTableRowView *)tableView: (NSTableView *)tableView rowViewForRow: (NSInteger)row\n{\n\treturn [[STTableRowView alloc] initWithTableView: tableView];\n}\n\n@end\n"
  },
  {
    "path": "Plugin/States/StatesWindow.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"10117\" systemVersion=\"15G31\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"10117\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"StatesController\">\n            <connections>\n                <outlet property=\"addNewStateButton\" destination=\"bUH-iu-jsD\" id=\"oP9-Tp-6VA\"/>\n                <outlet property=\"placeholderView\" destination=\"kJ8-YS-tjE\" id=\"Idz-y3-8vD\"/>\n                <outlet property=\"tableView\" destination=\"07i-xc-XA3\" id=\"kdR-uW-6yA\"/>\n                <outlet property=\"window\" destination=\"4Mh-eW-Wya\" id=\"xdh-bH-0LV\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <window title=\"State of the artboard\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" hidesOnDeactivate=\"YES\" oneShot=\"NO\" releasedWhenClosed=\"NO\" showsToolbarButton=\"NO\" visibleAtLaunch=\"NO\" animationBehavior=\"utilityWindow\" frameAutosaveName=\"\" id=\"4Mh-eW-Wya\" customClass=\"STWindow\">\n            <windowStyleMask key=\"styleMask\" closable=\"YES\" resizable=\"YES\" utility=\"YES\"/>\n            <windowPositionMask key=\"initialPositionMask\" leftStrut=\"YES\" rightStrut=\"YES\" topStrut=\"YES\" bottomStrut=\"YES\"/>\n            <rect key=\"contentRect\" x=\"120\" y=\"64\" width=\"200\" height=\"209\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"1280\" height=\"777\"/>\n            <value key=\"minSize\" type=\"size\" width=\"200\" height=\"209\"/>\n            <value key=\"maxSize\" type=\"size\" width=\"400\" height=\"450\"/>\n            <view key=\"contentView\" wantsLayer=\"YES\" id=\"AC7-AO-h07\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"200\" height=\"209\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <scrollView wantsLayer=\"YES\" borderType=\"none\" autohidesScrollers=\"YES\" horizontalLineScroll=\"26\" horizontalPageScroll=\"10\" verticalLineScroll=\"26\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"OXZ-wQ-2LX\" userLabel=\"Scroll View &gt; Table View\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"-1\" width=\"201\" height=\"181\"/>\n                        <clipView key=\"contentView\" wantsLayer=\"YES\" copiesOnScroll=\"NO\" id=\"6Tk-AU-SVX\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"201\" height=\"181\"/>\n                            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                            <subviews>\n                                <tableView wantsLayer=\"YES\" verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" columnAutoresizingStyle=\"lastColumnOnly\" alternatingRowBackgroundColors=\"YES\" columnReordering=\"NO\" columnResizing=\"NO\" emptySelection=\"NO\" autosaveColumns=\"NO\" typeSelect=\"NO\" rowHeight=\"24\" rowSizeStyle=\"automatic\" viewBased=\"YES\" id=\"07i-xc-XA3\" customClass=\"STTableView\">\n                                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"201\" height=\"0.0\"/>\n                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                    <size key=\"intercellSpacing\" width=\"3\" height=\"2\"/>\n                                    <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"gridColor\" name=\"gridColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <tableColumns>\n                                        <tableColumn width=\"198\" minWidth=\"40\" maxWidth=\"1000\" id=\"7M1-UH-Ceh\">\n                                            <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\" title=\"States\">\n                                                <font key=\"font\" metaFont=\"smallSystem\"/>\n                                                <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            </tableHeaderCell>\n                                            <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" title=\"Text Cell\" id=\"O8Z-y2-TwS\">\n                                                <font key=\"font\" metaFont=\"system\"/>\n                                                <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            </textFieldCell>\n                                            <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                            <prototypeCellViews>\n                                                <tableCellView identifier=\"StateCell\" wantsLayer=\"YES\" id=\"Ayr-wq-u12\" customClass=\"STTableCellView\">\n                                                    <rect key=\"frame\" x=\"1\" y=\"1\" width=\"198\" height=\"24\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                    <subviews>\n                                                        <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"CCU-9b-be0\" userLabel=\"Text label\" customClass=\"STTextField\">\n                                                            <rect key=\"frame\" x=\"13\" y=\"4\" width=\"177\" height=\"15\"/>\n                                                            <textFieldCell key=\"cell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" title=\"Table View Cell\" id=\"1ZX-ey-inf\">\n                                                                <font key=\"font\" size=\"11\" name=\"HelveticaNeue\"/>\n                                                                <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            </textFieldCell>\n                                                        </textField>\n                                                        <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"dNP-7B-gk9\" customClass=\"STUpdateButton\">\n                                                            <rect key=\"frame\" x=\"175\" y=\"3\" width=\"18\" height=\"18\"/>\n                                                            <constraints>\n                                                                <constraint firstAttribute=\"height\" constant=\"18\" id=\"fdz-Jt-1Bm\"/>\n                                                                <constraint firstAttribute=\"width\" constant=\"18\" id=\"qma-Em-KlE\"/>\n                                                            </constraints>\n                                                            <buttonCell key=\"cell\" type=\"roundRect\" bezelStyle=\"roundedRect\" image=\"dirty\" imagePosition=\"overlaps\" alignment=\"center\" state=\"on\" inset=\"2\" id=\"qRB-58-GY4\">\n                                                                <behavior key=\"behavior\" lightByContents=\"YES\"/>\n                                                                <font key=\"font\" metaFont=\"cellTitle\"/>\n                                                            </buttonCell>\n                                                        </button>\n                                                    </subviews>\n                                                    <constraints>\n                                                        <constraint firstItem=\"dNP-7B-gk9\" firstAttribute=\"centerY\" secondItem=\"Ayr-wq-u12\" secondAttribute=\"centerY\" id=\"Dmh-AX-n9z\"/>\n                                                        <constraint firstAttribute=\"trailing\" secondItem=\"CCU-9b-be0\" secondAttribute=\"trailing\" constant=\"10\" id=\"X45-p6-dfd\"/>\n                                                        <constraint firstItem=\"CCU-9b-be0\" firstAttribute=\"centerY\" secondItem=\"Ayr-wq-u12\" secondAttribute=\"centerY\" id=\"fcY-uv-GVj\"/>\n                                                        <constraint firstItem=\"CCU-9b-be0\" firstAttribute=\"leading\" secondItem=\"Ayr-wq-u12\" secondAttribute=\"leading\" constant=\"15\" id=\"wp3-cE-vYB\"/>\n                                                        <constraint firstAttribute=\"trailing\" secondItem=\"dNP-7B-gk9\" secondAttribute=\"trailing\" constant=\"5\" id=\"yfV-py-4GB\"/>\n                                                    </constraints>\n                                                    <connections>\n                                                        <outlet property=\"textField\" destination=\"CCU-9b-be0\" id=\"jwf-IV-Cmi\"/>\n                                                        <outlet property=\"updateButton\" destination=\"dNP-7B-gk9\" id=\"LVz-bM-gDT\"/>\n                                                    </connections>\n                                                </tableCellView>\n                                            </prototypeCellViews>\n                                        </tableColumn>\n                                    </tableColumns>\n                                    <connections>\n                                        <outlet property=\"dataSource\" destination=\"-2\" id=\"Zq2-Ir-6MC\"/>\n                                        <outlet property=\"delegate\" destination=\"-2\" id=\"oXL-e8-I5y\"/>\n                                    </connections>\n                                </tableView>\n                            </subviews>\n                            <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </clipView>\n                        <scroller key=\"horizontalScroller\" hidden=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"0to-v7-jGH\">\n                            <rect key=\"frame\" x=\"1\" y=\"7\" width=\"0.0\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\"/>\n                        </scroller>\n                        <scroller key=\"verticalScroller\" hidden=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"euO-nB-O4Y\">\n                            <rect key=\"frame\" x=\"224\" y=\"17\" width=\"15\" height=\"102\"/>\n                            <autoresizingMask key=\"autoresizingMask\"/>\n                        </scroller>\n                    </scrollView>\n                    <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ix5-5p-Z47\" userLabel=\"Header\" customClass=\"STHeaderView\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"180\" width=\"200\" height=\"29\"/>\n                        <subviews>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"UmN-oM-s3R\">\n                                <rect key=\"frame\" x=\"8\" y=\"4\" width=\"141\" height=\"20\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" title=\"States\" id=\"r2q-s2-7mS\">\n                                    <font key=\"font\" size=\"11\" name=\"HelveticaNeue-Medium\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <button focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bUH-iu-jsD\">\n                                <rect key=\"frame\" x=\"177\" y=\"7\" width=\"15\" height=\"15\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"15\" id=\"K4H-bj-a6y\"/>\n                                </constraints>\n                                <buttonCell key=\"cell\" type=\"roundRect\" bezelStyle=\"roundedRect\" image=\"NSAddTemplate\" imagePosition=\"overlaps\" alignment=\"center\" controlSize=\"mini\" state=\"on\" focusRingType=\"none\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"UKR-xN-a3S\">\n                                    <behavior key=\"behavior\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"miniSystem\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"createNewState:\" target=\"-2\" id=\"cjU-27-vdh\"/>\n                                </connections>\n                            </button>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"bUH-iu-jsD\" firstAttribute=\"top\" secondItem=\"ix5-5p-Z47\" secondAttribute=\"top\" constant=\"7\" id=\"EJe-Bg-j8P\"/>\n                            <constraint firstItem=\"UmN-oM-s3R\" firstAttribute=\"centerY\" secondItem=\"bUH-iu-jsD\" secondAttribute=\"centerY\" constant=\"0.5\" id=\"Vam-G2-haU\"/>\n                            <constraint firstItem=\"UmN-oM-s3R\" firstAttribute=\"centerY\" secondItem=\"ix5-5p-Z47\" secondAttribute=\"centerY\" constant=\"0.5\" id=\"dSa-qb-KDV\"/>\n                            <constraint firstItem=\"UmN-oM-s3R\" firstAttribute=\"leading\" secondItem=\"ix5-5p-Z47\" secondAttribute=\"leading\" constant=\"10\" id=\"p0l-kg-ihF\"/>\n                            <constraint firstItem=\"UmN-oM-s3R\" firstAttribute=\"top\" secondItem=\"ix5-5p-Z47\" secondAttribute=\"top\" constant=\"5\" id=\"tcK-Kp-oPm\"/>\n                            <constraint firstItem=\"bUH-iu-jsD\" firstAttribute=\"leading\" secondItem=\"UmN-oM-s3R\" secondAttribute=\"trailing\" constant=\"30\" id=\"xvC-Gc-zRQ\"/>\n                            <constraint firstAttribute=\"height\" constant=\"29\" id=\"zUC-Ev-mtC\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"bUH-iu-jsD\" secondAttribute=\"trailing\" constant=\"8\" id=\"ze3-HS-OV2\"/>\n                        </constraints>\n                    </customView>\n                    <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kJ8-YS-tjE\" userLabel=\"Placeholder\" customClass=\"STPlaceholderView\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"200\" height=\"180\"/>\n                        <subviews>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gP8-61-j5v\">\n                                <rect key=\"frame\" x=\"58\" y=\"83\" width=\"85\" height=\"15\"/>\n                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" sendsActionOnEndEditing=\"YES\" alignment=\"center\" title=\"Select Artboard\" id=\"lLG-eO-fVS\">\n                                    <font key=\"font\" size=\"11\" name=\"HelveticaNeue\"/>\n                                    <color key=\"textColor\" name=\"controlShadowColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"gP8-61-j5v\" firstAttribute=\"centerY\" secondItem=\"kJ8-YS-tjE\" secondAttribute=\"centerY\" id=\"RTa-qh-s78\"/>\n                            <constraint firstItem=\"gP8-61-j5v\" firstAttribute=\"centerX\" secondItem=\"kJ8-YS-tjE\" secondAttribute=\"centerX\" id=\"fcm-fJ-MBY\"/>\n                        </constraints>\n                    </customView>\n                </subviews>\n                <constraints>\n                    <constraint firstItem=\"kJ8-YS-tjE\" firstAttribute=\"leading\" secondItem=\"OXZ-wQ-2LX\" secondAttribute=\"leading\" id=\"5gV-iM-yRK\"/>\n                    <constraint firstItem=\"ix5-5p-Z47\" firstAttribute=\"trailing\" secondItem=\"kJ8-YS-tjE\" secondAttribute=\"trailing\" id=\"CEK-fC-EX7\"/>\n                    <constraint firstItem=\"OXZ-wQ-2LX\" firstAttribute=\"top\" secondItem=\"kJ8-YS-tjE\" secondAttribute=\"top\" id=\"RGI-BC-b7M\"/>\n                    <constraint firstItem=\"kJ8-YS-tjE\" firstAttribute=\"centerX\" secondItem=\"OXZ-wQ-2LX\" secondAttribute=\"centerX\" id=\"akp-07-RRn\"/>\n                    <constraint firstItem=\"ix5-5p-Z47\" firstAttribute=\"top\" secondItem=\"AC7-AO-h07\" secondAttribute=\"top\" id=\"g4V-kq-nBF\"/>\n                    <constraint firstItem=\"OXZ-wQ-2LX\" firstAttribute=\"top\" secondItem=\"ix5-5p-Z47\" secondAttribute=\"bottom\" id=\"ieD-j5-hmN\"/>\n                    <constraint firstItem=\"OXZ-wQ-2LX\" firstAttribute=\"leading\" secondItem=\"AC7-AO-h07\" secondAttribute=\"leading\" id=\"kea-YR-61J\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"OXZ-wQ-2LX\" secondAttribute=\"bottom\" constant=\"-1\" id=\"nJS-vU-NZ4\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"OXZ-wQ-2LX\" secondAttribute=\"trailing\" constant=\"-1\" id=\"rua-FM-uAa\"/>\n                    <constraint firstItem=\"ix5-5p-Z47\" firstAttribute=\"leading\" secondItem=\"kJ8-YS-tjE\" secondAttribute=\"leading\" id=\"tdl-jz-NsO\"/>\n                    <constraint firstItem=\"kJ8-YS-tjE\" firstAttribute=\"centerY\" secondItem=\"OXZ-wQ-2LX\" secondAttribute=\"centerY\" id=\"uAc-eO-kV4\"/>\n                </constraints>\n            </view>\n            <point key=\"canvasLocation\" x=\"-1136\" y=\"222.5\"/>\n        </window>\n    </objects>\n    <resources>\n        <image name=\"NSAddTemplate\" width=\"11\" height=\"11\"/>\n        <image name=\"dirty\" width=\"12\" height=\"12\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Plugin/States.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t0A12AE5E1D13A62300CBB026 /* STStatefulArtboard+Snapshots.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A12AE5D1D13A62300CBB026 /* STStatefulArtboard+Snapshots.m */; };\n\t\t0A2C50EA1D09C87800CB3C9F /* STWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A2C50E91D09C87800CB3C9F /* STWindow.m */; };\n\t\t0A3CBDB31D0A61C40016EFD8 /* STTableRowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A3CBDB21D0A61C40016EFD8 /* STTableRowView.m */; };\n\t\t0A3CBDB61D0A6BB10016EFD8 /* STColorFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A3CBDB51D0A6BB10016EFD8 /* STColorFactory.m */; };\n\t\t0A3CEE731D055B6F008A4BB0 /* StatesController+Naming.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A3CEE721D055B6F008A4BB0 /* StatesController+Naming.m */; };\n\t\t0A3CEE761D055C5E008A4BB0 /* StatesController+Decisions.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A3CEE751D055C5E008A4BB0 /* StatesController+Decisions.m */; };\n\t\t0A3CEE791D05693E008A4BB0 /* StatesController+ContextMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A3CEE781D05693E008A4BB0 /* StatesController+ContextMenu.m */; };\n\t\t0A4BDCAE1CFEBDC600D3584F /* STSketch.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A4BDCAD1CFEBDC600D3584F /* STSketch.m */; };\n\t\t0A4BDCB61CFEC5C200D3584F /* Aspects.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A4BDCB51CFEC5C200D3584F /* Aspects.m */; };\n\t\t0A4BDCBA1CFED17200D3584F /* STSketchPluginContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A4BDCB91CFED17200D3584F /* STSketchPluginContext.m */; };\n\t\t0A7160F31D09279C008A3F78 /* STUpdateButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A7160F21D09279C008A3F78 /* STUpdateButton.m */; };\n\t\t0A9BE3C61D06F89E00257F99 /* dirty.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A9BE3C41D06F89E00257F99 /* dirty.png */; };\n\t\t0A9BE3C71D06F89E00257F99 /* dirty@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A9BE3C51D06F89E00257F99 /* dirty@2x.png */; };\n\t\t0A9C85941D0B001B00231073 /* STPlaceholderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A9C85931D0B001B00231073 /* STPlaceholderView.m */; };\n\t\t0A9CBE3E1D09D8C700748DFA /* STTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A9CBE3D1D09D8C700748DFA /* STTableCellView.m */; };\n\t\t0A9CBE411D09DEFB00748DFA /* STHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A9CBE401D09DEFB00748DFA /* STHeaderView.m */; };\n\t\t0AAB1C541CFF33C8006512AF /* STLayerState.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AAB1C531CFF33C8006512AF /* STLayerState.m */; };\n\t\t0AAB1C5B1CFF3D56006512AF /* STStateDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AAB1C5A1CFF3D56006512AF /* STStateDescription.m */; };\n\t\t0AAB1C5E1CFF40CA006512AF /* STStatefulArtboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AAB1C5D1CFF40CA006512AF /* STStatefulArtboard.m */; };\n\t\t0AB737AC1D04512600E79D3D /* STTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AB737AB1D04512600E79D3D /* STTableView.m */; };\n\t\t0AC4CD911D0BDDD000829E45 /* STTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AC4CD901D0BDDD000829E45 /* STTextField.m */; };\n\t\t0AC4CD941D0BE52300829E45 /* NSArray+HigherOrder.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AC4CD931D0BE52300829E45 /* NSArray+HigherOrder.m */; };\n\t\t0AD7BE051CFDE548003C77BB /* StatesController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AD7BE041CFDE548003C77BB /* StatesController.m */; };\n\t\t0AD7BE0B1CFDF088003C77BB /* StatesWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0AD7BE0A1CFDF088003C77BB /* StatesWindow.xib */; };\n\t\t0AE014F61D0EA24C00F39C32 /* NSArray+Indexes.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AE014F51D0EA24C00F39C32 /* NSArray+Indexes.m */; };\n\t\t0AE014F91D0EB3EA00F39C32 /* StatesController+DragNDrop.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AE014F81D0EB3EA00F39C32 /* StatesController+DragNDrop.m */; };\n\t\t0AE8BF421D02FC6E00E0C4A8 /* STStatefulArtboard+Backend.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AE8BF411D02FC6E00E0C4A8 /* STStatefulArtboard+Backend.m */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t0A12AE5C1D13A62300CBB026 /* STStatefulArtboard+Snapshots.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"STStatefulArtboard+Snapshots.h\"; sourceTree = \"<group>\"; };\n\t\t0A12AE5D1D13A62300CBB026 /* STStatefulArtboard+Snapshots.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"STStatefulArtboard+Snapshots.m\"; sourceTree = \"<group>\"; };\n\t\t0A291EA81D59BF6E0003F2A3 /* Versioning.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Versioning.xcconfig; sourceTree = \"<group>\"; };\n\t\t0A291EAB1D59C0A10003F2A3 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = \"<group>\"; };\n\t\t0A291EAD1D59C0AA0003F2A3 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = \"<group>\"; };\n\t\t0A2C50E81D09C87800CB3C9F /* STWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STWindow.h; sourceTree = \"<group>\"; };\n\t\t0A2C50E91D09C87800CB3C9F /* STWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STWindow.m; sourceTree = \"<group>\"; };\n\t\t0A3CBDB11D0A61C40016EFD8 /* STTableRowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STTableRowView.h; sourceTree = \"<group>\"; };\n\t\t0A3CBDB21D0A61C40016EFD8 /* STTableRowView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STTableRowView.m; sourceTree = \"<group>\"; };\n\t\t0A3CBDB41D0A6BB10016EFD8 /* STColorFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STColorFactory.h; sourceTree = \"<group>\"; };\n\t\t0A3CBDB51D0A6BB10016EFD8 /* STColorFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STColorFactory.m; sourceTree = \"<group>\"; };\n\t\t0A3CE5971CFCBB6800B8C552 /* States.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = States.bundle; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t0A3CE59A1CFCBB6800B8C552 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t0A3CE5A01CFCBBCD00B8C552 /* manifest.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = manifest.json; sourceTree = \"<group>\"; };\n\t\t0A3CEE711D055B6F008A4BB0 /* StatesController+Naming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = \"StatesController+Naming.h\"; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };\n\t\t0A3CEE721D055B6F008A4BB0 /* StatesController+Naming.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = \"StatesController+Naming.m\"; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };\n\t\t0A3CEE741D055C5E008A4BB0 /* StatesController+Decisions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = \"StatesController+Decisions.h\"; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };\n\t\t0A3CEE751D055C5E008A4BB0 /* StatesController+Decisions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = \"StatesController+Decisions.m\"; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };\n\t\t0A3CEE771D05693E008A4BB0 /* StatesController+ContextMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = \"StatesController+ContextMenu.h\"; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };\n\t\t0A3CEE781D05693E008A4BB0 /* StatesController+ContextMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = \"StatesController+ContextMenu.m\"; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };\n\t\t0A4BDCAC1CFEBDC600D3584F /* STSketch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STSketch.h; sourceTree = \"<group>\"; };\n\t\t0A4BDCAD1CFEBDC600D3584F /* STSketch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STSketch.m; sourceTree = \"<group>\"; };\n\t\t0A4BDCB41CFEC5C200D3584F /* Aspects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Aspects.h; path = vendor/Aspects.h; sourceTree = \"<group>\"; };\n\t\t0A4BDCB51CFEC5C200D3584F /* Aspects.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Aspects.m; path = vendor/Aspects.m; sourceTree = \"<group>\"; };\n\t\t0A4BDCB81CFED17200D3584F /* STSketchPluginContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STSketchPluginContext.h; sourceTree = \"<group>\"; };\n\t\t0A4BDCB91CFED17200D3584F /* STSketchPluginContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STSketchPluginContext.m; sourceTree = \"<group>\"; };\n\t\t0A7160F11D09279C008A3F78 /* STUpdateButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STUpdateButton.h; sourceTree = \"<group>\"; };\n\t\t0A7160F21D09279C008A3F78 /* STUpdateButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STUpdateButton.m; sourceTree = \"<group>\"; };\n\t\t0A7E78FF1CFED94800CAB318 /* runtime.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = runtime.js; path = lib/runtime.js; sourceTree = \"<group>\"; };\n\t\t0A9BE3C41D06F89E00257F99 /* dirty.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = dirty.png; sourceTree = \"<group>\"; };\n\t\t0A9BE3C51D06F89E00257F99 /* dirty@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"dirty@2x.png\"; sourceTree = \"<group>\"; };\n\t\t0A9C85921D0B001B00231073 /* STPlaceholderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STPlaceholderView.h; sourceTree = \"<group>\"; };\n\t\t0A9C85931D0B001B00231073 /* STPlaceholderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STPlaceholderView.m; sourceTree = \"<group>\"; };\n\t\t0A9CBE3C1D09D8C700748DFA /* STTableCellView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STTableCellView.h; sourceTree = \"<group>\"; };\n\t\t0A9CBE3D1D09D8C700748DFA /* STTableCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STTableCellView.m; sourceTree = \"<group>\"; };\n\t\t0A9CBE3F1D09DEFB00748DFA /* STHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STHeaderView.h; sourceTree = \"<group>\"; };\n\t\t0A9CBE401D09DEFB00748DFA /* STHeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STHeaderView.m; sourceTree = \"<group>\"; };\n\t\t0AAB1C4A1CFF2FEB006512AF /* STPage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STPage.h; sourceTree = \"<group>\"; };\n\t\t0AAB1C4B1CFF2FF6006512AF /* STDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDocument.h; sourceTree = \"<group>\"; };\n\t\t0AAB1C4C1CFF2FFE006512AF /* STLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STLayer.h; sourceTree = \"<group>\"; };\n\t\t0AAB1C4D1CFF3006006512AF /* STArtboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STArtboard.h; sourceTree = \"<group>\"; };\n\t\t0AAB1C501CFF3217006512AF /* STCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STCommand.h; sourceTree = \"<group>\"; };\n\t\t0AAB1C521CFF33C8006512AF /* STLayerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STLayerState.h; sourceTree = \"<group>\"; };\n\t\t0AAB1C531CFF33C8006512AF /* STLayerState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STLayerState.m; sourceTree = \"<group>\"; };\n\t\t0AAB1C591CFF3D56006512AF /* STStateDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STStateDescription.h; sourceTree = \"<group>\"; };\n\t\t0AAB1C5A1CFF3D56006512AF /* STStateDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STStateDescription.m; sourceTree = \"<group>\"; };\n\t\t0AAB1C5C1CFF40CA006512AF /* STStatefulArtboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STStatefulArtboard.h; sourceTree = \"<group>\"; };\n\t\t0AAB1C5D1CFF40CA006512AF /* STStatefulArtboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STStatefulArtboard.m; sourceTree = \"<group>\"; };\n\t\t0AB737AA1D04512600E79D3D /* STTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STTableView.h; sourceTree = \"<group>\"; };\n\t\t0AB737AB1D04512600E79D3D /* STTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STTableView.m; sourceTree = \"<group>\"; };\n\t\t0AC4CD8F1D0BDDD000829E45 /* STTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STTextField.h; sourceTree = \"<group>\"; };\n\t\t0AC4CD901D0BDDD000829E45 /* STTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STTextField.m; sourceTree = \"<group>\"; };\n\t\t0AC4CD921D0BE52300829E45 /* NSArray+HigherOrder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"NSArray+HigherOrder.h\"; sourceTree = \"<group>\"; };\n\t\t0AC4CD931D0BE52300829E45 /* NSArray+HigherOrder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"NSArray+HigherOrder.m\"; sourceTree = \"<group>\"; };\n\t\t0AD7BE031CFDE548003C77BB /* StatesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = StatesController.h; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };\n\t\t0AD7BE041CFDE548003C77BB /* StatesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = StatesController.m; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };\n\t\t0AD7BE081CFDE680003C77BB /* plugin.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; lineEnding = 0; path = plugin.js; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.javascript; };\n\t\t0AD7BE0A1CFDF088003C77BB /* StatesWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StatesWindow.xib; sourceTree = \"<group>\"; };\n\t\t0AE014F41D0EA24C00F39C32 /* NSArray+Indexes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"NSArray+Indexes.h\"; sourceTree = \"<group>\"; };\n\t\t0AE014F51D0EA24C00F39C32 /* NSArray+Indexes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"NSArray+Indexes.m\"; sourceTree = \"<group>\"; };\n\t\t0AE014F71D0EB3EA00F39C32 /* StatesController+DragNDrop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"StatesController+DragNDrop.h\"; sourceTree = \"<group>\"; };\n\t\t0AE014F81D0EB3EA00F39C32 /* StatesController+DragNDrop.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"StatesController+DragNDrop.m\"; sourceTree = \"<group>\"; };\n\t\t0AE8BF401D02FC6E00E0C4A8 /* STStatefulArtboard+Backend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"STStatefulArtboard+Backend.h\"; sourceTree = \"<group>\"; };\n\t\t0AE8BF411D02FC6E00E0C4A8 /* STStatefulArtboard+Backend.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"STStatefulArtboard+Backend.m\"; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t0A3CE5941CFCBB6800B8C552 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t0A291EAA1D59C0820003F2A3 /* Build Configuration */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0A291EA81D59BF6E0003F2A3 /* Versioning.xcconfig */,\n\t\t\t\t0A291EAB1D59C0A10003F2A3 /* Debug.xcconfig */,\n\t\t\t\t0A291EAD1D59C0AA0003F2A3 /* Release.xcconfig */,\n\t\t\t);\n\t\t\tname = \"Build Configuration\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0A3CE58E1CFCBB6800B8C552 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0A291EAA1D59C0820003F2A3 /* Build Configuration */,\n\t\t\t\t0A3CE5A01CFCBBCD00B8C552 /* manifest.json */,\n\t\t\t\t0AD7BE071CFDE658003C77BB /* JS */,\n\t\t\t\t0A3CE5991CFCBB6800B8C552 /* Native Code */,\n\t\t\t\t0AE8BF431D030E7C00E0C4A8 /* Helpers */,\n\t\t\t\t0A9BE3C31D06F89E00257F99 /* Images */,\n\t\t\t\t0A4BDCB01CFEC37000D3584F /* Vendor */,\n\t\t\t\t0A3CE5981CFCBB6800B8C552 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0A3CE5981CFCBB6800B8C552 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0A3CE5971CFCBB6800B8C552 /* States.bundle */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0A3CE5991CFCBB6800B8C552 /* Native Code */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0A3CE59A1CFCBB6800B8C552 /* Info.plist */,\n\t\t\t\t0A3CBDB41D0A6BB10016EFD8 /* STColorFactory.h */,\n\t\t\t\t0A3CBDB51D0A6BB10016EFD8 /* STColorFactory.m */,\n\t\t\t\t0AAB1C5F1CFF4AE8006512AF /* Controller */,\n\t\t\t\t0A7160F41D0927A5008A3F78 /* Views */,\n\t\t\t\t0A3CEE7A1D0569DF008A4BB0 /* Artboards */,\n\t\t\t\t0AAB1C511CFF33B8006512AF /* Wrappers */,\n\t\t\t\t0AAB1C4E1CFF31C1006512AF /* Sketch Protocols */,\n\t\t\t);\n\t\t\tname = \"Native Code\";\n\t\t\tpath = States;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0A3CEE7A1D0569DF008A4BB0 /* Artboards */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0AAB1C5C1CFF40CA006512AF /* STStatefulArtboard.h */,\n\t\t\t\t0AAB1C5D1CFF40CA006512AF /* STStatefulArtboard.m */,\n\t\t\t\t0A12AE5C1D13A62300CBB026 /* STStatefulArtboard+Snapshots.h */,\n\t\t\t\t0A12AE5D1D13A62300CBB026 /* STStatefulArtboard+Snapshots.m */,\n\t\t\t\t0AE8BF401D02FC6E00E0C4A8 /* STStatefulArtboard+Backend.h */,\n\t\t\t\t0AE8BF411D02FC6E00E0C4A8 /* STStatefulArtboard+Backend.m */,\n\t\t\t);\n\t\t\tname = Artboards;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0A4BDCB01CFEC37000D3584F /* Vendor */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0A4BDCB41CFEC5C200D3584F /* Aspects.h */,\n\t\t\t\t0A4BDCB51CFEC5C200D3584F /* Aspects.m */,\n\t\t\t);\n\t\t\tname = Vendor;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0A7160F41D0927A5008A3F78 /* Views */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0A7160F11D09279C008A3F78 /* STUpdateButton.h */,\n\t\t\t\t0A7160F21D09279C008A3F78 /* STUpdateButton.m */,\n\t\t\t\t0AB737AA1D04512600E79D3D /* STTableView.h */,\n\t\t\t\t0AB737AB1D04512600E79D3D /* STTableView.m */,\n\t\t\t\t0A9CBE3C1D09D8C700748DFA /* STTableCellView.h */,\n\t\t\t\t0A9CBE3D1D09D8C700748DFA /* STTableCellView.m */,\n\t\t\t\t0AC4CD8F1D0BDDD000829E45 /* STTextField.h */,\n\t\t\t\t0AC4CD901D0BDDD000829E45 /* STTextField.m */,\n\t\t\t\t0A3CBDB11D0A61C40016EFD8 /* STTableRowView.h */,\n\t\t\t\t0A3CBDB21D0A61C40016EFD8 /* STTableRowView.m */,\n\t\t\t\t0A2C50E81D09C87800CB3C9F /* STWindow.h */,\n\t\t\t\t0A2C50E91D09C87800CB3C9F /* STWindow.m */,\n\t\t\t\t0A9CBE3F1D09DEFB00748DFA /* STHeaderView.h */,\n\t\t\t\t0A9CBE401D09DEFB00748DFA /* STHeaderView.m */,\n\t\t\t\t0A9C85921D0B001B00231073 /* STPlaceholderView.h */,\n\t\t\t\t0A9C85931D0B001B00231073 /* STPlaceholderView.m */,\n\t\t\t);\n\t\t\tname = Views;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0A7E79001CFEDA1500CAB318 /* lib */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0A7E78FF1CFED94800CAB318 /* runtime.js */,\n\t\t\t);\n\t\t\tname = lib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0A9BE3C31D06F89E00257F99 /* Images */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0A9BE3C41D06F89E00257F99 /* dirty.png */,\n\t\t\t\t0A9BE3C51D06F89E00257F99 /* dirty@2x.png */,\n\t\t\t);\n\t\t\tpath = Images;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0AAB1C4E1CFF31C1006512AF /* Sketch Protocols */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0AAB1C4A1CFF2FEB006512AF /* STPage.h */,\n\t\t\t\t0AAB1C4B1CFF2FF6006512AF /* STDocument.h */,\n\t\t\t\t0AAB1C4C1CFF2FFE006512AF /* STLayer.h */,\n\t\t\t\t0AAB1C4D1CFF3006006512AF /* STArtboard.h */,\n\t\t\t\t0AAB1C501CFF3217006512AF /* STCommand.h */,\n\t\t\t);\n\t\t\tname = \"Sketch Protocols\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0AAB1C511CFF33B8006512AF /* Wrappers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0A4BDCAC1CFEBDC600D3584F /* STSketch.h */,\n\t\t\t\t0A4BDCAD1CFEBDC600D3584F /* STSketch.m */,\n\t\t\t\t0AAB1C521CFF33C8006512AF /* STLayerState.h */,\n\t\t\t\t0AAB1C531CFF33C8006512AF /* STLayerState.m */,\n\t\t\t\t0AAB1C591CFF3D56006512AF /* STStateDescription.h */,\n\t\t\t\t0AAB1C5A1CFF3D56006512AF /* STStateDescription.m */,\n\t\t\t\t0A4BDCB81CFED17200D3584F /* STSketchPluginContext.h */,\n\t\t\t\t0A4BDCB91CFED17200D3584F /* STSketchPluginContext.m */,\n\t\t\t);\n\t\t\tname = Wrappers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0AAB1C5F1CFF4AE8006512AF /* Controller */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0AD7BE0A1CFDF088003C77BB /* StatesWindow.xib */,\n\t\t\t\t0AD7BE031CFDE548003C77BB /* StatesController.h */,\n\t\t\t\t0AD7BE041CFDE548003C77BB /* StatesController.m */,\n\t\t\t\t0A3CEE711D055B6F008A4BB0 /* StatesController+Naming.h */,\n\t\t\t\t0A3CEE721D055B6F008A4BB0 /* StatesController+Naming.m */,\n\t\t\t\t0A3CEE741D055C5E008A4BB0 /* StatesController+Decisions.h */,\n\t\t\t\t0A3CEE751D055C5E008A4BB0 /* StatesController+Decisions.m */,\n\t\t\t\t0A3CEE771D05693E008A4BB0 /* StatesController+ContextMenu.h */,\n\t\t\t\t0A3CEE781D05693E008A4BB0 /* StatesController+ContextMenu.m */,\n\t\t\t\t0AE014F71D0EB3EA00F39C32 /* StatesController+DragNDrop.h */,\n\t\t\t\t0AE014F81D0EB3EA00F39C32 /* StatesController+DragNDrop.m */,\n\t\t\t);\n\t\t\tname = Controller;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0AD7BE071CFDE658003C77BB /* JS */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0AD7BE081CFDE680003C77BB /* plugin.js */,\n\t\t\t\t0A7E79001CFEDA1500CAB318 /* lib */,\n\t\t\t);\n\t\t\tname = JS;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0AE8BF431D030E7C00E0C4A8 /* Helpers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0AC4CD921D0BE52300829E45 /* NSArray+HigherOrder.h */,\n\t\t\t\t0AC4CD931D0BE52300829E45 /* NSArray+HigherOrder.m */,\n\t\t\t\t0AE014F41D0EA24C00F39C32 /* NSArray+Indexes.h */,\n\t\t\t\t0AE014F51D0EA24C00F39C32 /* NSArray+Indexes.m */,\n\t\t\t);\n\t\t\tname = Helpers;\n\t\t\tpath = States;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t0A3CE5961CFCBB6800B8C552 /* States */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 0A3CE59D1CFCBB6800B8C552 /* Build configuration list for PBXNativeTarget \"States\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t0A291EA71D59BE830003F2A3 /* Set Info for Source Version Load Command */,\n\t\t\t\t0A3CE5931CFCBB6800B8C552 /* Sources */,\n\t\t\t\t0A3CE5941CFCBB6800B8C552 /* Frameworks */,\n\t\t\t\t0A3CE5951CFCBB6800B8C552 /* Resources */,\n\t\t\t\t0AD7BE061CFDE5A2003C77BB /* Build Sketch plugin */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = States;\n\t\t\tproductName = States;\n\t\t\tproductReference = 0A3CE5971CFCBB6800B8C552 /* States.bundle */;\n\t\t\tproductType = \"com.apple.product-type.bundle\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t0A3CE58F1CFCBB6800B8C552 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0730;\n\t\t\t\tORGANIZATIONNAME = \"Internals Exposed\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t0A3CE5961CFCBB6800B8C552 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 0A3CE5921CFCBB6800B8C552 /* Build configuration list for PBXProject \"States\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = 0A3CE58E1CFCBB6800B8C552;\n\t\t\tproductRefGroup = 0A3CE5981CFCBB6800B8C552 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t0A3CE5961CFCBB6800B8C552 /* States */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t0A3CE5951CFCBB6800B8C552 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t0A9BE3C71D06F89E00257F99 /* dirty@2x.png in Resources */,\n\t\t\t\t0A9BE3C61D06F89E00257F99 /* dirty.png in Resources */,\n\t\t\t\t0AD7BE0B1CFDF088003C77BB /* StatesWindow.xib in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t0A291EA71D59BE830003F2A3 /* Set Info for Source Version Load Command */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Set Info for Source Version Load Command\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"VERSIONING_XCCONFIG_FILE=\\\"${PROJECT_DIR}/Versioning.xcconfig\\\"\\nPROJECT_VERSION=$(/usr/libexec/PlistBuddy -c \\\"Print CFBundleShortVersionString\\\" \\\"${PROJECT_DIR}/${INFOPLIST_FILE}\\\")\\necho \\\"IEXP_SOURCE_VERSION = $PROJECT_VERSION\\\" > $VERSIONING_XCCONFIG_FILE\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t0AD7BE061CFDE5A2003C77BB /* Build Sketch plugin */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Build Sketch plugin\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"PLUGIN_DIR=\\\"$BUILT_PRODUCTS_DIR/$PROJECT_NAME\\\".sketchplugin\\n# 1) create a .sketchplugin directory with the following subdirs:\\n#    ./Contents/Sketch\\n#    ./Contents/Sketch/lib\\n#    ./Contents/Resources\\nrm -Rf \\\"$PLUGIN_DIR\\\"\\nmkdir \\\"$PLUGIN_DIR\\\" && cd $_\\nmkdir ./Contents && cd $_\\nmkdir -p ./Sketch/lib\\nmkdir ./Resources\\n# 2) copy files into .sketchplugin:\\n#    ./Contents/Sketch/manifest.json\\n#    ./Contents/Sketch/*.js\\n#    ./Contents/Sketch/lib/*.js\\n#    ./Contents/Resources/States.bundle\\ncp \\\"$PROJECT_DIR/manifest.json\\\" ./Sketch\\ncp \\\"$PROJECT_DIR/\\\"*.js ./Sketch\\ncp \\\"$PROJECT_DIR/lib/\\\"*.js ./Sketch/lib\\ncp -R \\\"$BUILT_PRODUCTS_DIR/$EXECUTABLE_NAME.bundle\\\" ./Resources\\n# 3) Symlink our target into Sketch's Plugins directory\\ncd ~/Library/Application\\\\ Support/com.bohemiancoding.sketch3/Plugins\\nrm -f \\\"$EXECUTABLE_NAME\\\".sketchplugin\\nln -s \\\"$PLUGIN_DIR\\\" \\\"$EXECUTABLE_NAME\\\".sketchplugin\\n# 4) Done! 🎉\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t0A3CE5931CFCBB6800B8C552 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t0AD7BE051CFDE548003C77BB /* StatesController.m in Sources */,\n\t\t\t\t0A3CEE761D055C5E008A4BB0 /* StatesController+Decisions.m in Sources */,\n\t\t\t\t0AC4CD911D0BDDD000829E45 /* STTextField.m in Sources */,\n\t\t\t\t0AAB1C541CFF33C8006512AF /* STLayerState.m in Sources */,\n\t\t\t\t0A4BDCAE1CFEBDC600D3584F /* STSketch.m in Sources */,\n\t\t\t\t0A9CBE411D09DEFB00748DFA /* STHeaderView.m in Sources */,\n\t\t\t\t0A3CBDB61D0A6BB10016EFD8 /* STColorFactory.m in Sources */,\n\t\t\t\t0A3CEE731D055B6F008A4BB0 /* StatesController+Naming.m in Sources */,\n\t\t\t\t0A3CEE791D05693E008A4BB0 /* StatesController+ContextMenu.m in Sources */,\n\t\t\t\t0A12AE5E1D13A62300CBB026 /* STStatefulArtboard+Snapshots.m in Sources */,\n\t\t\t\t0AC4CD941D0BE52300829E45 /* NSArray+HigherOrder.m in Sources */,\n\t\t\t\t0A9CBE3E1D09D8C700748DFA /* STTableCellView.m in Sources */,\n\t\t\t\t0AAB1C5B1CFF3D56006512AF /* STStateDescription.m in Sources */,\n\t\t\t\t0AE8BF421D02FC6E00E0C4A8 /* STStatefulArtboard+Backend.m in Sources */,\n\t\t\t\t0AAB1C5E1CFF40CA006512AF /* STStatefulArtboard.m in Sources */,\n\t\t\t\t0AE014F91D0EB3EA00F39C32 /* StatesController+DragNDrop.m in Sources */,\n\t\t\t\t0A4BDCBA1CFED17200D3584F /* STSketchPluginContext.m in Sources */,\n\t\t\t\t0AE014F61D0EA24C00F39C32 /* NSArray+Indexes.m in Sources */,\n\t\t\t\t0AB737AC1D04512600E79D3D /* STTableView.m in Sources */,\n\t\t\t\t0A9C85941D0B001B00231073 /* STPlaceholderView.m in Sources */,\n\t\t\t\t0A7160F31D09279C008A3F78 /* STUpdateButton.m in Sources */,\n\t\t\t\t0A4BDCB61CFEC5C200D3584F /* Aspects.m in Sources */,\n\t\t\t\t0A2C50EA1D09C87800CB3C9F /* STWindow.m in Sources */,\n\t\t\t\t0A3CBDB31D0A61C40016EFD8 /* STTableRowView.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t0A3CE59B1CFCBB6800B8C552 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.10;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t0A3CE59C1CFCBB6800B8C552 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.10;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t0A3CE59E1CFCBB6800B8C552 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 0A291EAB1D59C0A10003F2A3 /* Debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application: Dmitry Rodionov (C6QG5C28K7)\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = States/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Bundles\";\n\t\t\t\tOTHER_LDFLAGS = \"$(inherited)\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.edenvidal.states-for-sketch\";\n\t\t\t\tPRODUCT_NAME = States;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tWRAPPER_EXTENSION = bundle;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t0A3CE59F1CFCBB6800B8C552 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 0A291EAD1D59C0AA0003F2A3 /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application: Dmitry Rodionov (C6QG5C28K7)\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = States/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Bundles\";\n\t\t\t\tOTHER_LDFLAGS = \"$(inherited)\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.edenvidal.states-for-sketch\";\n\t\t\t\tPRODUCT_NAME = States;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tWRAPPER_EXTENSION = bundle;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t0A3CE5921CFCBB6800B8C552 /* Build configuration list for PBXProject \"States\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t0A3CE59B1CFCBB6800B8C552 /* Debug */,\n\t\t\t\t0A3CE59C1CFCBB6800B8C552 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t0A3CE59D1CFCBB6800B8C552 /* Build configuration list for PBXNativeTarget \"States\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t0A3CE59E1CFCBB6800B8C552 /* Debug */,\n\t\t\t\t0A3CE59F1CFCBB6800B8C552 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 0A3CE58F1CFCBB6800B8C552 /* Project object */;\n}\n"
  },
  {
    "path": "Plugin/States.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:/Users/rodionovd/Code/Contracting/States/States.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Plugin/States.xcodeproj/xcshareddata/xcschemes/States for Beta.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0730\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"0A3CE5961CFCBB6800B8C552\"\n               BuildableName = \"States.bundle\"\n               BlueprintName = \"States\"\n               ReferencedContainer = \"container:States.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <PathRunnable\n         runnableDebuggingMode = \"0\"\n         BundleIdentifier = \"com.bohemiancoding.sketch3.beta\"\n         FilePath = \"/Applications/Sketch Beta.app\">\n      </PathRunnable>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"0A3CE5961CFCBB6800B8C552\"\n            BuildableName = \"States.bundle\"\n            BlueprintName = \"States\"\n            ReferencedContainer = \"container:States.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"0A3CE5961CFCBB6800B8C552\"\n            BuildableName = \"States.bundle\"\n            BlueprintName = \"States\"\n            ReferencedContainer = \"container:States.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "Plugin/States.xcodeproj/xcshareddata/xcschemes/States.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0730\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"0A3CE5961CFCBB6800B8C552\"\n               BuildableName = \"States.bundle\"\n               BlueprintName = \"States\"\n               ReferencedContainer = \"container:States.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <PathRunnable\n         runnableDebuggingMode = \"0\"\n         BundleIdentifier = \"com.bohemiancoding.sketch3\"\n         FilePath = \"/Applications/Sketch.app\">\n      </PathRunnable>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"0A3CE5961CFCBB6800B8C552\"\n            BuildableName = \"States.bundle\"\n            BlueprintName = \"States\"\n            ReferencedContainer = \"container:States.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"0A3CE5961CFCBB6800B8C552\"\n            BuildableName = \"States.bundle\"\n            BlueprintName = \"States\"\n            ReferencedContainer = \"container:States.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "Plugin/Versioning.xcconfig",
    "content": "IEXP_SOURCE_VERSION = 1.0.0\n"
  },
  {
    "path": "Plugin/lib/runtime.js",
    "content": "// runtime.js\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n(function(){\n\tthis.runtime = {};\n\t/// This function fetches the plugin path from a current script path\n\tthis.runtime.pluginPath = function()\n\t{\n\t\tvar result = [NSString stringWithString: coscript.env().scriptURL.path()];\n\t\twhile(result.lastPathComponent().pathExtension() != \"sketchplugin\"){\n\t\t\tresult = result.stringByDeletingLastPathComponent();\n\t\t}\n\t\treturn result;\n\t}\n\t/// This function loads a bundle with the given name located in Resources directory\n \t/// of this plugin\n \tthis.runtime.loadBundle = function(bundleName)\n\t{\n\t\tvar bundlePath = runtime.pluginPath() + \"/Contents/Resources/\" + bundleName;\n\t\tvar bundle = [NSBundle bundleWithPath: bundlePath];\n\t\tbundle.load();\n\t}\n})();\n"
  },
  {
    "path": "Plugin/manifest.json",
    "content": "{\n\t\"name\": \"States\",\n\t\"description\": \"Create different artboard states and switch between them easily\",\n\t\"author\": \"Eden Vidal\",\n\t\"homepage\": \"http://edenvidal.com\",\n\t\"version\": \"1.0.0\",\n\t\"identifier\": \"com.edenvidal.states-for-sketch\",\n\t\"compatibleVersion\": 3,\n\t\"bundleVersion\": 1,\n\t\"commands\": [{\n\t\t\"name\": \"Show States\",\n\t\t\"identifier\": \"show-states\",\n\t\t\"script\": \"plugin.js\",\n\t\t\"handler\": \"showStatesWindow\"\n\t\t}],\n\t\"menu\": {\n\t\t\"items\": [\"show-states\"],\n\t\t\"isRoot\": true\n\t}\n}\n"
  },
  {
    "path": "Plugin/plugin.js",
    "content": "// plugin.js\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import \"lib/runtime.js\"\n\nfunction showStatesWindow(context)\n{\n\tif (NSClassFromString(\"STStatesController\") == null) {\n\t\truntime.loadBundle(\"States.bundle\");\n\t\t[STSketch setPluginContextDictionary: context];\n\t}\n\n\tvar controller = [StatesController defaultController];\n\tif ([[controller window] isVisible]) {\n\t\t[[controller window] close];\n\t} else {\n\t\t[controller showWindow: nil];\n\t}\n    [STSketch toggleStatesPluginName];\n}\n"
  },
  {
    "path": "Plugin/vendor/Aspects.h",
    "content": "//\n//  Aspects.h\n//  Aspects - A delightful, simple library for aspect oriented programming.\n//\n//  Copyright (c) 2014 Peter Steinberger. Licensed under the MIT license.\n//\n\n#import <Foundation/Foundation.h>\n\ntypedef NS_OPTIONS(NSUInteger, AspectOptions) {\n    AspectPositionAfter   = 0,            /// Called after the original implementation (default)\n    AspectPositionInstead = 1,            /// Will replace the original implementation.\n    AspectPositionBefore  = 2,            /// Called before the original implementation.\n    \n    AspectOptionAutomaticRemoval = 1 << 3 /// Will remove the hook after the first execution.\n};\n\n/// Opaque Aspect Token that allows to deregister the hook.\n@protocol AspectToken <NSObject>\n\n/// Deregisters an aspect.\n/// @return YES if deregistration is successful, otherwise NO.\n- (BOOL)remove;\n\n@end\n\n/// The AspectInfo protocol is the first parameter of our block syntax.\n@protocol AspectInfo <NSObject>\n\n/// The instance that is currently hooked.\n- (id)instance;\n\n/// The original invocation of the hooked method.\n- (NSInvocation *)originalInvocation;\n\n/// All method arguments, boxed. This is lazily evaluated.\n- (NSArray *)arguments;\n\n@end\n\n/**\n Aspects uses Objective-C message forwarding to hook into messages. This will create some overhead. Don't add aspects to methods that are called a lot. Aspects is meant for view/controller code that is not called a 1000 times per second.\n\n Adding aspects returns an opaque token which can be used to deregister again. All calls are thread safe.\n */\n@interface NSObject (Aspects)\n\n/// Adds a block of code before/instead/after the current `selector` for a specific class.\n///\n/// @param block Aspects replicates the type signature of the method being hooked.\n/// The first parameter will be `id<AspectInfo>`, followed by all parameters of the method.\n/// These parameters are optional and will be filled to match the block signature.\n/// You can even use an empty block, or one that simple gets `id<AspectInfo>`.\n///\n/// @note Hooking static methods is not supported.\n/// @return A token which allows to later deregister the aspect.\n+ (id<AspectToken>)aspect_hookSelector:(SEL)selector\n                           withOptions:(AspectOptions)options\n                            usingBlock:(id)block\n                                 error:(NSError **)error;\n\n/// Adds a block of code before/instead/after the current `selector` for a specific instance.\n- (id<AspectToken>)aspect_hookSelector:(SEL)selector\n                           withOptions:(AspectOptions)options\n                            usingBlock:(id)block\n                                 error:(NSError **)error;\n\n@end\n\n\ntypedef NS_ENUM(NSUInteger, AspectErrorCode) {\n    AspectErrorSelectorBlacklisted,                   /// Selectors like release, retain, autorelease are blacklisted.\n    AspectErrorDoesNotRespondToSelector,              /// Selector could not be found.\n    AspectErrorSelectorDeallocPosition,               /// When hooking dealloc, only AspectPositionBefore is allowed.\n    AspectErrorSelectorAlreadyHookedInClassHierarchy, /// Statically hooking the same method in subclasses is not allowed.\n    AspectErrorFailedToAllocateClassPair,             /// The runtime failed creating a class pair.\n    AspectErrorMissingBlockSignature,                 /// The block misses compile time signature info and can't be called.\n    AspectErrorIncompatibleBlockSignature,            /// The block signature does not match the method or is too large.\n\n    AspectErrorRemoveObjectAlreadyDeallocated = 100   /// (for removing) The object hooked is already deallocated.\n};\n\nextern NSString *const AspectErrorDomain;\n"
  },
  {
    "path": "Plugin/vendor/Aspects.m",
    "content": "//\n//  Aspects.m\n//  Aspects - A delightful, simple library for aspect oriented programming.\n//\n//  Copyright (c) 2014 Peter Steinberger. Licensed under the MIT license.\n//\n\n#import \"Aspects.h\"\n#import <libkern/OSAtomic.h>\n#import <objc/runtime.h>\n#import <objc/message.h>\n\n#define AspectLog(...)\n//#define AspectLog(...) do { NSLog(__VA_ARGS__); }while(0)\n#define AspectLogError(...) do { NSLog(__VA_ARGS__); }while(0)\n\n// Block internals.\ntypedef NS_OPTIONS(int, AspectBlockFlags) {\n\tAspectBlockFlagsHasCopyDisposeHelpers = (1 << 25),\n\tAspectBlockFlagsHasSignature          = (1 << 30)\n};\ntypedef struct _AspectBlock {\n\t__unused Class isa;\n\tAspectBlockFlags flags;\n\t__unused int reserved;\n\tvoid (__unused *invoke)(struct _AspectBlock *block, ...);\n\tstruct {\n\t\tunsigned long int reserved;\n\t\tunsigned long int size;\n\t\t// requires AspectBlockFlagsHasCopyDisposeHelpers\n\t\tvoid (*copy)(void *dst, const void *src);\n\t\tvoid (*dispose)(const void *);\n\t\t// requires AspectBlockFlagsHasSignature\n\t\tconst char *signature;\n\t\tconst char *layout;\n\t} *descriptor;\n\t// imported variables\n} *AspectBlockRef;\n\n@interface AspectInfo : NSObject <AspectInfo>\n- (id)initWithInstance:(__unsafe_unretained id)instance invocation:(NSInvocation *)invocation;\n@property (nonatomic, unsafe_unretained, readonly) id instance;\n@property (nonatomic, strong, readonly) NSArray *arguments;\n@property (nonatomic, strong, readonly) NSInvocation *originalInvocation;\n@end\n\n// Tracks a single aspect.\n@interface AspectIdentifier : NSObject\n+ (instancetype)identifierWithSelector:(SEL)selector object:(id)object options:(AspectOptions)options block:(id)block error:(NSError **)error;\n- (BOOL)invokeWithInfo:(id<AspectInfo>)info;\n@property (nonatomic, assign) SEL selector;\n@property (nonatomic, strong) id block;\n@property (nonatomic, strong) NSMethodSignature *blockSignature;\n@property (nonatomic, weak) id object;\n@property (nonatomic, assign) AspectOptions options;\n@end\n\n// Tracks all aspects for an object/class.\n@interface AspectsContainer : NSObject\n- (void)addAspect:(AspectIdentifier *)aspect withOptions:(AspectOptions)injectPosition;\n- (BOOL)removeAspect:(id)aspect;\n- (BOOL)hasAspects;\n@property (atomic, copy) NSArray *beforeAspects;\n@property (atomic, copy) NSArray *insteadAspects;\n@property (atomic, copy) NSArray *afterAspects;\n@end\n\n@interface AspectTracker : NSObject\n- (id)initWithTrackedClass:(Class)trackedClass;\n@property (nonatomic, strong) Class trackedClass;\n@property (nonatomic, readonly) NSString *trackedClassName;\n@property (nonatomic, strong) NSMutableSet *selectorNames;\n@property (nonatomic, strong) NSMutableDictionary *selectorNamesToSubclassTrackers;\n- (void)addSubclassTracker:(AspectTracker *)subclassTracker hookingSelectorName:(NSString *)selectorName;\n- (void)removeSubclassTracker:(AspectTracker *)subclassTracker hookingSelectorName:(NSString *)selectorName;\n- (BOOL)subclassHasHookedSelectorName:(NSString *)selectorName;\n- (NSSet *)subclassTrackersHookingSelectorName:(NSString *)selectorName;\n@end\n\n@interface NSInvocation (Aspects)\n- (NSArray *)aspects_arguments;\n@end\n\n#define AspectPositionFilter 0x07\n\n#define AspectError(errorCode, errorDescription) do { \\\nAspectLogError(@\"Aspects: %@\", errorDescription); \\\nif (error) { *error = [NSError errorWithDomain:AspectErrorDomain code:errorCode userInfo:@{NSLocalizedDescriptionKey: errorDescription}]; }}while(0)\n\nNSString *const AspectErrorDomain = @\"AspectErrorDomain\";\nstatic NSString *const AspectsSubclassSuffix = @\"_Aspects_\";\nstatic NSString *const AspectsMessagePrefix = @\"aspects_\";\n\n@implementation NSObject (Aspects)\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Public Aspects API\n\n+ (id<AspectToken>)aspect_hookSelector:(SEL)selector\n                      withOptions:(AspectOptions)options\n                       usingBlock:(id)block\n                            error:(NSError **)error {\n    return aspect_add((id)self, selector, options, block, error);\n}\n\n/// @return A token which allows to later deregister the aspect.\n- (id<AspectToken>)aspect_hookSelector:(SEL)selector\n                      withOptions:(AspectOptions)options\n                       usingBlock:(id)block\n                            error:(NSError **)error {\n    return aspect_add(self, selector, options, block, error);\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Private Helper\n\nstatic id aspect_add(id self, SEL selector, AspectOptions options, id block, NSError **error) {\n    NSCParameterAssert(self);\n    NSCParameterAssert(selector);\n    NSCParameterAssert(block);\n\n    __block AspectIdentifier *identifier = nil;\n    aspect_performLocked(^{\n        if (aspect_isSelectorAllowedAndTrack(self, selector, options, error)) {\n            AspectsContainer *aspectContainer = aspect_getContainerForObject(self, selector);\n            identifier = [AspectIdentifier identifierWithSelector:selector object:self options:options block:block error:error];\n            if (identifier) {\n                [aspectContainer addAspect:identifier withOptions:options];\n\n                // Modify the class to allow message interception.\n                aspect_prepareClassAndHookSelector(self, selector, error);\n            }\n        }\n    });\n    return identifier;\n}\n\nstatic BOOL aspect_remove(AspectIdentifier *aspect, NSError **error) {\n    NSCAssert([aspect isKindOfClass:AspectIdentifier.class], @\"Must have correct type.\");\n\n    __block BOOL success = NO;\n    aspect_performLocked(^{\n        id self = aspect.object; // strongify\n        if (self) {\n            AspectsContainer *aspectContainer = aspect_getContainerForObject(self, aspect.selector);\n            success = [aspectContainer removeAspect:aspect];\n\n            aspect_cleanupHookedClassAndSelector(self, aspect.selector);\n            // destroy token\n            aspect.object = nil;\n            aspect.block = nil;\n            aspect.selector = NULL;\n        }else {\n            NSString *errrorDesc = [NSString stringWithFormat:@\"Unable to deregister hook. Object already deallocated: %@\", aspect];\n            AspectError(AspectErrorRemoveObjectAlreadyDeallocated, errrorDesc);\n        }\n    });\n    return success;\n}\n\nstatic void aspect_performLocked(dispatch_block_t block) {\n    static OSSpinLock aspect_lock = OS_SPINLOCK_INIT;\n    OSSpinLockLock(&aspect_lock);\n    block();\n    OSSpinLockUnlock(&aspect_lock);\n}\n\nstatic SEL aspect_aliasForSelector(SEL selector) {\n    NSCParameterAssert(selector);\n\treturn NSSelectorFromString([AspectsMessagePrefix stringByAppendingFormat:@\"_%@\", NSStringFromSelector(selector)]);\n}\n\nstatic NSMethodSignature *aspect_blockMethodSignature(id block, NSError **error) {\n    AspectBlockRef layout = (__bridge void *)block;\n\tif (!(layout->flags & AspectBlockFlagsHasSignature)) {\n        NSString *description = [NSString stringWithFormat:@\"The block %@ doesn't contain a type signature.\", block];\n        AspectError(AspectErrorMissingBlockSignature, description);\n        return nil;\n    }\n\tvoid *desc = layout->descriptor;\n\tdesc += 2 * sizeof(unsigned long int);\n\tif (layout->flags & AspectBlockFlagsHasCopyDisposeHelpers) {\n\t\tdesc += 2 * sizeof(void *);\n    }\n\tif (!desc) {\n        NSString *description = [NSString stringWithFormat:@\"The block %@ doesn't has a type signature.\", block];\n        AspectError(AspectErrorMissingBlockSignature, description);\n        return nil;\n    }\n\tconst char *signature = (*(const char **)desc);\n\treturn [NSMethodSignature signatureWithObjCTypes:signature];\n}\n\nstatic BOOL aspect_isCompatibleBlockSignature(NSMethodSignature *blockSignature, id object, SEL selector, NSError **error) {\n    NSCParameterAssert(blockSignature);\n    NSCParameterAssert(object);\n    NSCParameterAssert(selector);\n\n    BOOL signaturesMatch = YES;\n    NSMethodSignature *methodSignature = [[object class] instanceMethodSignatureForSelector:selector];\n    if (blockSignature.numberOfArguments > methodSignature.numberOfArguments) {\n        signaturesMatch = NO;\n    }else {\n        if (blockSignature.numberOfArguments > 1) {\n            const char *blockType = [blockSignature getArgumentTypeAtIndex:1];\n            if (blockType[0] != '@') {\n                signaturesMatch = NO;\n            }\n        }\n        // Argument 0 is self/block, argument 1 is SEL or id<AspectInfo>. We start comparing at argument 2.\n        // The block can have less arguments than the method, that's ok.\n        if (signaturesMatch) {\n            for (NSUInteger idx = 2; idx < blockSignature.numberOfArguments; idx++) {\n                const char *methodType = [methodSignature getArgumentTypeAtIndex:idx];\n                const char *blockType = [blockSignature getArgumentTypeAtIndex:idx];\n                // Only compare parameter, not the optional type data.\n                if (!methodType || !blockType || methodType[0] != blockType[0]) {\n                    signaturesMatch = NO; break;\n                }\n            }\n        }\n    }\n\n    if (!signaturesMatch) {\n        NSString *description = [NSString stringWithFormat:@\"Block signature %@ doesn't match %@.\", blockSignature, methodSignature];\n        AspectError(AspectErrorIncompatibleBlockSignature, description);\n        return NO;\n    }\n    return YES;\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Class + Selector Preparation\n\nstatic BOOL aspect_isMsgForwardIMP(IMP impl) {\n    return impl == _objc_msgForward\n#if !defined(__arm64__)\n    || impl == (IMP)_objc_msgForward_stret\n#endif\n    ;\n}\n\nstatic IMP aspect_getMsgForwardIMP(NSObject *self, SEL selector) {\n    IMP msgForwardIMP = _objc_msgForward;\n#if !defined(__arm64__)\n    // As an ugly internal runtime implementation detail in the 32bit runtime, we need to determine of the method we hook returns a struct or anything larger than id.\n    // https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/LowLevelABI/000-Introduction/introduction.html\n    // https://github.com/ReactiveCocoa/ReactiveCocoa/issues/783\n    // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf (Section 5.4)\n    Method method = class_getInstanceMethod(self.class, selector);\n    const char *encoding = method_getTypeEncoding(method);\n    BOOL methodReturnsStructValue = encoding[0] == _C_STRUCT_B;\n    if (methodReturnsStructValue) {\n        @try {\n            NSUInteger valueSize = 0;\n            NSGetSizeAndAlignment(encoding, &valueSize, NULL);\n\n            if (valueSize == 1 || valueSize == 2 || valueSize == 4 || valueSize == 8) {\n                methodReturnsStructValue = NO;\n            }\n        } @catch (__unused NSException *e) {}\n    }\n    if (methodReturnsStructValue) {\n        msgForwardIMP = (IMP)_objc_msgForward_stret;\n    }\n#endif\n    return msgForwardIMP;\n}\n\nstatic void aspect_prepareClassAndHookSelector(NSObject *self, SEL selector, NSError **error) {\n    NSCParameterAssert(selector);\n    Class klass = aspect_hookClass(self, error);\n    Method targetMethod = class_getInstanceMethod(klass, selector);\n    IMP targetMethodIMP = method_getImplementation(targetMethod);\n    if (!aspect_isMsgForwardIMP(targetMethodIMP)) {\n        // Make a method alias for the existing method implementation, it not already copied.\n        const char *typeEncoding = method_getTypeEncoding(targetMethod);\n        SEL aliasSelector = aspect_aliasForSelector(selector);\n        if (![klass instancesRespondToSelector:aliasSelector]) {\n            __unused BOOL addedAlias = class_addMethod(klass, aliasSelector, method_getImplementation(targetMethod), typeEncoding);\n            NSCAssert(addedAlias, @\"Original implementation for %@ is already copied to %@ on %@\", NSStringFromSelector(selector), NSStringFromSelector(aliasSelector), klass);\n        }\n\n        // We use forwardInvocation to hook in.\n        class_replaceMethod(klass, selector, aspect_getMsgForwardIMP(self, selector), typeEncoding);\n        AspectLog(@\"Aspects: Installed hook for -[%@ %@].\", klass, NSStringFromSelector(selector));\n    }\n}\n\n// Will undo the runtime changes made.\nstatic void aspect_cleanupHookedClassAndSelector(NSObject *self, SEL selector) {\n    NSCParameterAssert(self);\n    NSCParameterAssert(selector);\n\n\tClass klass = object_getClass(self);\n    BOOL isMetaClass = class_isMetaClass(klass);\n    if (isMetaClass) {\n        klass = (Class)self;\n    }\n\n    // Check if the method is marked as forwarded and undo that.\n    Method targetMethod = class_getInstanceMethod(klass, selector);\n    IMP targetMethodIMP = method_getImplementation(targetMethod);\n    if (aspect_isMsgForwardIMP(targetMethodIMP)) {\n        // Restore the original method implementation.\n        const char *typeEncoding = method_getTypeEncoding(targetMethod);\n        SEL aliasSelector = aspect_aliasForSelector(selector);\n        Method originalMethod = class_getInstanceMethod(klass, aliasSelector);\n        IMP originalIMP = method_getImplementation(originalMethod);\n        NSCAssert(originalMethod, @\"Original implementation for %@ not found %@ on %@\", NSStringFromSelector(selector), NSStringFromSelector(aliasSelector), klass);\n\n        class_replaceMethod(klass, selector, originalIMP, typeEncoding);\n        AspectLog(@\"Aspects: Removed hook for -[%@ %@].\", klass, NSStringFromSelector(selector));\n    }\n\n    // Deregister global tracked selector\n    aspect_deregisterTrackedSelector(self, selector);\n\n    // Get the aspect container and check if there are any hooks remaining. Clean up if there are not.\n    AspectsContainer *container = aspect_getContainerForObject(self, selector);\n    if (!container.hasAspects) {\n        // Destroy the container\n        aspect_destroyContainerForObject(self, selector);\n\n        // Figure out how the class was modified to undo the changes.\n        NSString *className = NSStringFromClass(klass);\n        if ([className hasSuffix:AspectsSubclassSuffix]) {\n            Class originalClass = NSClassFromString([className stringByReplacingOccurrencesOfString:AspectsSubclassSuffix withString:@\"\"]);\n            NSCAssert(originalClass != nil, @\"Original class must exist\");\n            object_setClass(self, originalClass);\n            AspectLog(@\"Aspects: %@ has been restored.\", NSStringFromClass(originalClass));\n\n            // We can only dispose the class pair if we can ensure that no instances exist using our subclass.\n            // Since we don't globally track this, we can't ensure this - but there's also not much overhead in keeping it around.\n            //objc_disposeClassPair(object.class);\n        }else {\n            // Class is most likely swizzled in place. Undo that.\n            if (isMetaClass) {\n                aspect_undoSwizzleClassInPlace((Class)self);\n            }else if (self.class != klass) {\n            \taspect_undoSwizzleClassInPlace(klass);\n            }\n        }\n    }\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Hook Class\n\nstatic Class aspect_hookClass(NSObject *self, NSError **error) {\n    NSCParameterAssert(self);\n\tClass statedClass = self.class;\n\tClass baseClass = object_getClass(self);\n\tNSString *className = NSStringFromClass(baseClass);\n\n    // Already subclassed\n\tif ([className hasSuffix:AspectsSubclassSuffix]) {\n\t\treturn baseClass;\n\n        // We swizzle a class object, not a single object.\n\t}else if (class_isMetaClass(baseClass)) {\n        return aspect_swizzleClassInPlace((Class)self);\n        // Probably a KVO'ed class. Swizzle in place. Also swizzle meta classes in place.\n    }else if (statedClass != baseClass) {\n        return aspect_swizzleClassInPlace(baseClass);\n    }\n\n    // Default case. Create dynamic subclass.\n\tconst char *subclassName = [className stringByAppendingString:AspectsSubclassSuffix].UTF8String;\n\tClass subclass = objc_getClass(subclassName);\n\n\tif (subclass == nil) {\n\t\tsubclass = objc_allocateClassPair(baseClass, subclassName, 0);\n\t\tif (subclass == nil) {\n            NSString *errrorDesc = [NSString stringWithFormat:@\"objc_allocateClassPair failed to allocate class %s.\", subclassName];\n            AspectError(AspectErrorFailedToAllocateClassPair, errrorDesc);\n            return nil;\n        }\n\n\t\taspect_swizzleForwardInvocation(subclass);\n\t\taspect_hookedGetClass(subclass, statedClass);\n\t\taspect_hookedGetClass(object_getClass(subclass), statedClass);\n\t\tobjc_registerClassPair(subclass);\n\t}\n\n\tobject_setClass(self, subclass);\n\treturn subclass;\n}\n\nstatic NSString *const AspectsForwardInvocationSelectorName = @\"__aspects_forwardInvocation:\";\nstatic void aspect_swizzleForwardInvocation(Class klass) {\n    NSCParameterAssert(klass);\n    // If there is no method, replace will act like class_addMethod.\n    IMP originalImplementation = class_replaceMethod(klass, @selector(forwardInvocation:), (IMP)__ASPECTS_ARE_BEING_CALLED__, \"v@:@\");\n    if (originalImplementation) {\n        class_addMethod(klass, NSSelectorFromString(AspectsForwardInvocationSelectorName), originalImplementation, \"v@:@\");\n    }\n    AspectLog(@\"Aspects: %@ is now aspect aware.\", NSStringFromClass(klass));\n}\n\nstatic void aspect_undoSwizzleForwardInvocation(Class klass) {\n    NSCParameterAssert(klass);\n    Method originalMethod = class_getInstanceMethod(klass, NSSelectorFromString(AspectsForwardInvocationSelectorName));\n    Method objectMethod = class_getInstanceMethod(NSObject.class, @selector(forwardInvocation:));\n    // There is no class_removeMethod, so the best we can do is to retore the original implementation, or use a dummy.\n    IMP originalImplementation = method_getImplementation(originalMethod ?: objectMethod);\n    class_replaceMethod(klass, @selector(forwardInvocation:), originalImplementation, \"v@:@\");\n\n    AspectLog(@\"Aspects: %@ has been restored.\", NSStringFromClass(klass));\n}\n\nstatic void aspect_hookedGetClass(Class class, Class statedClass) {\n    NSCParameterAssert(class);\n    NSCParameterAssert(statedClass);\n\tMethod method = class_getInstanceMethod(class, @selector(class));\n\tIMP newIMP = imp_implementationWithBlock(^(id self) {\n\t\treturn statedClass;\n\t});\n\tclass_replaceMethod(class, @selector(class), newIMP, method_getTypeEncoding(method));\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Swizzle Class In Place\n\nstatic void _aspect_modifySwizzledClasses(void (^block)(NSMutableSet *swizzledClasses)) {\n    static NSMutableSet *swizzledClasses;\n    static dispatch_once_t pred;\n    dispatch_once(&pred, ^{\n        swizzledClasses = [NSMutableSet new];\n    });\n    @synchronized(swizzledClasses) {\n        block(swizzledClasses);\n    }\n}\n\nstatic Class aspect_swizzleClassInPlace(Class klass) {\n    NSCParameterAssert(klass);\n    NSString *className = NSStringFromClass(klass);\n\n    _aspect_modifySwizzledClasses(^(NSMutableSet *swizzledClasses) {\n        if (![swizzledClasses containsObject:className]) {\n            aspect_swizzleForwardInvocation(klass);\n            [swizzledClasses addObject:className];\n        }\n    });\n    return klass;\n}\n\nstatic void aspect_undoSwizzleClassInPlace(Class klass) {\n    NSCParameterAssert(klass);\n    NSString *className = NSStringFromClass(klass);\n\n    _aspect_modifySwizzledClasses(^(NSMutableSet *swizzledClasses) {\n        if ([swizzledClasses containsObject:className]) {\n            aspect_undoSwizzleForwardInvocation(klass);\n            [swizzledClasses removeObject:className];\n        }\n    });\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Aspect Invoke Point\n\n// This is a macro so we get a cleaner stack trace.\n#define aspect_invoke(aspects, info) \\\nfor (AspectIdentifier *aspect in aspects) {\\\n    [aspect invokeWithInfo:info];\\\n    if (aspect.options & AspectOptionAutomaticRemoval) { \\\n        aspectsToRemove = [aspectsToRemove?:@[] arrayByAddingObject:aspect]; \\\n    } \\\n}\n\n// This is the swizzled forwardInvocation: method.\nstatic void __ASPECTS_ARE_BEING_CALLED__(__unsafe_unretained NSObject *self, SEL selector, NSInvocation *invocation) {\n    NSCParameterAssert(self);\n    NSCParameterAssert(invocation);\n    SEL originalSelector = invocation.selector;\n\tSEL aliasSelector = aspect_aliasForSelector(invocation.selector);\n    invocation.selector = aliasSelector;\n    AspectsContainer *objectContainer = objc_getAssociatedObject(self, aliasSelector);\n    AspectsContainer *classContainer = aspect_getContainerForClass(object_getClass(self), aliasSelector);\n    AspectInfo *info = [[AspectInfo alloc] initWithInstance:self invocation:invocation];\n    NSArray *aspectsToRemove = nil;\n\n    // Before hooks.\n    aspect_invoke(classContainer.beforeAspects, info);\n    aspect_invoke(objectContainer.beforeAspects, info);\n\n    // Instead hooks.\n    BOOL respondsToAlias = YES;\n    if (objectContainer.insteadAspects.count || classContainer.insteadAspects.count) {\n        aspect_invoke(classContainer.insteadAspects, info);\n        aspect_invoke(objectContainer.insteadAspects, info);\n    }else {\n        Class klass = object_getClass(invocation.target);\n        do {\n            if ((respondsToAlias = [klass instancesRespondToSelector:aliasSelector])) {\n                [invocation invoke];\n                break;\n            }\n        }while (!respondsToAlias && (klass = class_getSuperclass(klass)));\n    }\n\n    // After hooks.\n    aspect_invoke(classContainer.afterAspects, info);\n    aspect_invoke(objectContainer.afterAspects, info);\n\n    // If no hooks are installed, call original implementation (usually to throw an exception)\n    if (!respondsToAlias) {\n        invocation.selector = originalSelector;\n        SEL originalForwardInvocationSEL = NSSelectorFromString(AspectsForwardInvocationSelectorName);\n        if ([self respondsToSelector:originalForwardInvocationSEL]) {\n            ((void( *)(id, SEL, NSInvocation *))objc_msgSend)(self, originalForwardInvocationSEL, invocation);\n        }else {\n            [self doesNotRecognizeSelector:invocation.selector];\n        }\n    }\n\n    // Remove any hooks that are queued for deregistration.\n    [aspectsToRemove makeObjectsPerformSelector:@selector(remove)];\n}\n#undef aspect_invoke\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Aspect Container Management\n\n// Loads or creates the aspect container.\nstatic AspectsContainer *aspect_getContainerForObject(NSObject *self, SEL selector) {\n    NSCParameterAssert(self);\n    SEL aliasSelector = aspect_aliasForSelector(selector);\n    AspectsContainer *aspectContainer = objc_getAssociatedObject(self, aliasSelector);\n    if (!aspectContainer) {\n        aspectContainer = [AspectsContainer new];\n        objc_setAssociatedObject(self, aliasSelector, aspectContainer, OBJC_ASSOCIATION_RETAIN);\n    }\n    return aspectContainer;\n}\n\nstatic AspectsContainer *aspect_getContainerForClass(Class klass, SEL selector) {\n    NSCParameterAssert(klass);\n    AspectsContainer *classContainer = nil;\n    do {\n        classContainer = objc_getAssociatedObject(klass, selector);\n        if (classContainer.hasAspects) break;\n    }while ((klass = class_getSuperclass(klass)));\n\n    return classContainer;\n}\n\nstatic void aspect_destroyContainerForObject(id<NSObject> self, SEL selector) {\n    NSCParameterAssert(self);\n    SEL aliasSelector = aspect_aliasForSelector(selector);\n    objc_setAssociatedObject(self, aliasSelector, nil, OBJC_ASSOCIATION_RETAIN);\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - Selector Blacklist Checking\n\nstatic NSMutableDictionary *aspect_getSwizzledClassesDict() {\n    static NSMutableDictionary *swizzledClassesDict;\n    static dispatch_once_t pred;\n    dispatch_once(&pred, ^{\n        swizzledClassesDict = [NSMutableDictionary new];\n    });\n    return swizzledClassesDict;\n}\n\nstatic BOOL aspect_isSelectorAllowedAndTrack(NSObject *self, SEL selector, AspectOptions options, NSError **error) {\n    static NSSet *disallowedSelectorList;\n    static dispatch_once_t pred;\n    dispatch_once(&pred, ^{\n        disallowedSelectorList = [NSSet setWithObjects:@\"retain\", @\"release\", @\"autorelease\", @\"forwardInvocation:\", nil];\n    });\n\n    // Check against the blacklist.\n    NSString *selectorName = NSStringFromSelector(selector);\n    if ([disallowedSelectorList containsObject:selectorName]) {\n        NSString *errorDescription = [NSString stringWithFormat:@\"Selector %@ is blacklisted.\", selectorName];\n        AspectError(AspectErrorSelectorBlacklisted, errorDescription);\n        return NO;\n    }\n\n    // Additional checks.\n    AspectOptions position = options&AspectPositionFilter;\n    if ([selectorName isEqualToString:@\"dealloc\"] && position != AspectPositionBefore) {\n        NSString *errorDesc = @\"AspectPositionBefore is the only valid position when hooking dealloc.\";\n        AspectError(AspectErrorSelectorDeallocPosition, errorDesc);\n        return NO;\n    }\n\n    if (![self respondsToSelector:selector] && ![self.class instancesRespondToSelector:selector]) {\n        NSString *errorDesc = [NSString stringWithFormat:@\"Unable to find selector -[%@ %@].\", NSStringFromClass(self.class), selectorName];\n        AspectError(AspectErrorDoesNotRespondToSelector, errorDesc);\n        return NO;\n    }\n\n    // Search for the current class and the class hierarchy IF we are modifying a class object\n    if (class_isMetaClass(object_getClass(self))) {\n        Class klass = [self class];\n        NSMutableDictionary *swizzledClassesDict = aspect_getSwizzledClassesDict();\n        Class currentClass = [self class];\n\n        AspectTracker *tracker = swizzledClassesDict[currentClass];\n        if ([tracker subclassHasHookedSelectorName:selectorName]) {\n            NSSet *subclassTracker = [tracker subclassTrackersHookingSelectorName:selectorName];\n            NSSet *subclassNames = [subclassTracker valueForKey:@\"trackedClassName\"];\n            NSString *errorDescription = [NSString stringWithFormat:@\"Error: %@ already hooked subclasses: %@. A method can only be hooked once per class hierarchy.\", selectorName, subclassNames];\n            AspectError(AspectErrorSelectorAlreadyHookedInClassHierarchy, errorDescription);\n            return NO;\n        }\n\n        do {\n            tracker = swizzledClassesDict[currentClass];\n            if ([tracker.selectorNames containsObject:selectorName]) {\n                if (klass == currentClass) {\n                    // Already modified and topmost!\n                    return YES;\n                }\n                NSString *errorDescription = [NSString stringWithFormat:@\"Error: %@ already hooked in %@. A method can only be hooked once per class hierarchy.\", selectorName, NSStringFromClass(currentClass)];\n                AspectError(AspectErrorSelectorAlreadyHookedInClassHierarchy, errorDescription);\n                return NO;\n            }\n        } while ((currentClass = class_getSuperclass(currentClass)));\n\n        // Add the selector as being modified.\n        currentClass = klass;\n        AspectTracker *subclassTracker = nil;\n        do {\n            tracker = swizzledClassesDict[currentClass];\n            if (!tracker) {\n                tracker = [[AspectTracker alloc] initWithTrackedClass:currentClass];\n                swizzledClassesDict[(id<NSCopying>)currentClass] = tracker;\n            }\n            if (subclassTracker) {\n                [tracker addSubclassTracker:subclassTracker hookingSelectorName:selectorName];\n            } else {\n                [tracker.selectorNames addObject:selectorName];\n            }\n\n            // All superclasses get marked as having a subclass that is modified.\n            subclassTracker = tracker;\n        }while ((currentClass = class_getSuperclass(currentClass)));\n\t} else {\n\t\treturn YES;\n\t}\n\n    return YES;\n}\n\nstatic void aspect_deregisterTrackedSelector(id self, SEL selector) {\n    if (!class_isMetaClass(object_getClass(self))) return;\n\n    NSMutableDictionary *swizzledClassesDict = aspect_getSwizzledClassesDict();\n    NSString *selectorName = NSStringFromSelector(selector);\n    Class currentClass = [self class];\n    AspectTracker *subclassTracker = nil;\n    do {\n        AspectTracker *tracker = swizzledClassesDict[currentClass];\n        if (subclassTracker) {\n            [tracker removeSubclassTracker:subclassTracker hookingSelectorName:selectorName];\n        } else {\n            [tracker.selectorNames removeObject:selectorName];\n        }\n        if (tracker.selectorNames.count == 0 && tracker.selectorNamesToSubclassTrackers) {\n            [swizzledClassesDict removeObjectForKey:currentClass];\n        }\n        subclassTracker = tracker;\n    }while ((currentClass = class_getSuperclass(currentClass)));\n}\n\n@end\n\n@implementation AspectTracker\n\n- (id)initWithTrackedClass:(Class)trackedClass {\n    if (self = [super init]) {\n        _trackedClass = trackedClass;\n        _selectorNames = [NSMutableSet new];\n        _selectorNamesToSubclassTrackers = [NSMutableDictionary new];\n    }\n    return self;\n}\n\n- (BOOL)subclassHasHookedSelectorName:(NSString *)selectorName {\n    return self.selectorNamesToSubclassTrackers[selectorName] != nil;\n}\n\n- (void)addSubclassTracker:(AspectTracker *)subclassTracker hookingSelectorName:(NSString *)selectorName {\n    NSMutableSet *trackerSet = self.selectorNamesToSubclassTrackers[selectorName];\n    if (!trackerSet) {\n        trackerSet = [NSMutableSet new];\n        self.selectorNamesToSubclassTrackers[selectorName] = trackerSet;\n    }\n    [trackerSet addObject:subclassTracker];\n}\n- (void)removeSubclassTracker:(AspectTracker *)subclassTracker hookingSelectorName:(NSString *)selectorName {\n    NSMutableSet *trackerSet = self.selectorNamesToSubclassTrackers[selectorName];\n    [trackerSet removeObject:subclassTracker];\n    if (trackerSet.count == 0) {\n        [self.selectorNamesToSubclassTrackers removeObjectForKey:selectorName];\n    }\n}\n- (NSSet *)subclassTrackersHookingSelectorName:(NSString *)selectorName {\n    NSMutableSet *hookingSubclassTrackers = [NSMutableSet new];\n    for (AspectTracker *tracker in self.selectorNamesToSubclassTrackers[selectorName]) {\n        if ([tracker.selectorNames containsObject:selectorName]) {\n            [hookingSubclassTrackers addObject:tracker];\n        }\n        [hookingSubclassTrackers unionSet:[tracker subclassTrackersHookingSelectorName:selectorName]];\n    }\n    return hookingSubclassTrackers;\n}\n- (NSString *)trackedClassName {\n    return NSStringFromClass(self.trackedClass);\n}\n\n- (NSString *)description {\n    return [NSString stringWithFormat:@\"<%@: %@, trackedClass: %@, selectorNames:%@, subclass selector names: %@>\", self.class, self, NSStringFromClass(self.trackedClass), self.selectorNames, self.selectorNamesToSubclassTrackers.allKeys];\n}\n\n@end\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - NSInvocation (Aspects)\n\n@implementation NSInvocation (Aspects)\n\n// Thanks to the ReactiveCocoa team for providing a generic solution for this.\n- (id)aspect_argumentAtIndex:(NSUInteger)index {\n\tconst char *argType = [self.methodSignature getArgumentTypeAtIndex:index];\n\t// Skip const type qualifier.\n\tif (argType[0] == _C_CONST) argType++;\n\n#define WRAP_AND_RETURN(type) do { type val = 0; [self getArgument:&val atIndex:(NSInteger)index]; return @(val); } while (0)\n\tif (strcmp(argType, @encode(id)) == 0 || strcmp(argType, @encode(Class)) == 0) {\n\t\t__autoreleasing id returnObj;\n\t\t[self getArgument:&returnObj atIndex:(NSInteger)index];\n\t\treturn returnObj;\n\t} else if (strcmp(argType, @encode(SEL)) == 0) {\n        SEL selector = 0;\n        [self getArgument:&selector atIndex:(NSInteger)index];\n        return NSStringFromSelector(selector);\n    } else if (strcmp(argType, @encode(Class)) == 0) {\n        __autoreleasing Class theClass = Nil;\n        [self getArgument:&theClass atIndex:(NSInteger)index];\n        return theClass;\n        // Using this list will box the number with the appropriate constructor, instead of the generic NSValue.\n\t} else if (strcmp(argType, @encode(char)) == 0) {\n\t\tWRAP_AND_RETURN(char);\n\t} else if (strcmp(argType, @encode(int)) == 0) {\n\t\tWRAP_AND_RETURN(int);\n\t} else if (strcmp(argType, @encode(short)) == 0) {\n\t\tWRAP_AND_RETURN(short);\n\t} else if (strcmp(argType, @encode(long)) == 0) {\n\t\tWRAP_AND_RETURN(long);\n\t} else if (strcmp(argType, @encode(long long)) == 0) {\n\t\tWRAP_AND_RETURN(long long);\n\t} else if (strcmp(argType, @encode(unsigned char)) == 0) {\n\t\tWRAP_AND_RETURN(unsigned char);\n\t} else if (strcmp(argType, @encode(unsigned int)) == 0) {\n\t\tWRAP_AND_RETURN(unsigned int);\n\t} else if (strcmp(argType, @encode(unsigned short)) == 0) {\n\t\tWRAP_AND_RETURN(unsigned short);\n\t} else if (strcmp(argType, @encode(unsigned long)) == 0) {\n\t\tWRAP_AND_RETURN(unsigned long);\n\t} else if (strcmp(argType, @encode(unsigned long long)) == 0) {\n\t\tWRAP_AND_RETURN(unsigned long long);\n\t} else if (strcmp(argType, @encode(float)) == 0) {\n\t\tWRAP_AND_RETURN(float);\n\t} else if (strcmp(argType, @encode(double)) == 0) {\n\t\tWRAP_AND_RETURN(double);\n\t} else if (strcmp(argType, @encode(BOOL)) == 0) {\n\t\tWRAP_AND_RETURN(BOOL);\n\t} else if (strcmp(argType, @encode(bool)) == 0) {\n\t\tWRAP_AND_RETURN(BOOL);\n\t} else if (strcmp(argType, @encode(char *)) == 0) {\n\t\tWRAP_AND_RETURN(const char *);\n\t} else if (strcmp(argType, @encode(void (^)(void))) == 0) {\n\t\t__unsafe_unretained id block = nil;\n\t\t[self getArgument:&block atIndex:(NSInteger)index];\n\t\treturn [block copy];\n\t} else {\n\t\tNSUInteger valueSize = 0;\n\t\tNSGetSizeAndAlignment(argType, &valueSize, NULL);\n\n\t\tunsigned char valueBytes[valueSize];\n\t\t[self getArgument:valueBytes atIndex:(NSInteger)index];\n\n\t\treturn [NSValue valueWithBytes:valueBytes objCType:argType];\n\t}\n\treturn nil;\n#undef WRAP_AND_RETURN\n}\n\n- (NSArray *)aspects_arguments {\n\tNSMutableArray *argumentsArray = [NSMutableArray array];\n\tfor (NSUInteger idx = 2; idx < self.methodSignature.numberOfArguments; idx++) {\n\t\t[argumentsArray addObject:[self aspect_argumentAtIndex:idx] ?: NSNull.null];\n\t}\n\treturn [argumentsArray copy];\n}\n\n@end\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - AspectIdentifier\n\n@implementation AspectIdentifier\n\n+ (instancetype)identifierWithSelector:(SEL)selector object:(id)object options:(AspectOptions)options block:(id)block error:(NSError **)error {\n    NSCParameterAssert(block);\n    NSCParameterAssert(selector);\n    NSMethodSignature *blockSignature = aspect_blockMethodSignature(block, error); // TODO: check signature compatibility, etc.\n    if (!aspect_isCompatibleBlockSignature(blockSignature, object, selector, error)) {\n        return nil;\n    }\n\n    AspectIdentifier *identifier = nil;\n    if (blockSignature) {\n        identifier = [AspectIdentifier new];\n        identifier.selector = selector;\n        identifier.block = block;\n        identifier.blockSignature = blockSignature;\n        identifier.options = options;\n        identifier.object = object; // weak\n    }\n    return identifier;\n}\n\n- (BOOL)invokeWithInfo:(id<AspectInfo>)info {\n    NSInvocation *blockInvocation = [NSInvocation invocationWithMethodSignature:self.blockSignature];\n    NSInvocation *originalInvocation = info.originalInvocation;\n    NSUInteger numberOfArguments = self.blockSignature.numberOfArguments;\n\n    // Be extra paranoid. We already check that on hook registration.\n    if (numberOfArguments > originalInvocation.methodSignature.numberOfArguments) {\n        AspectLogError(@\"Block has too many arguments. Not calling %@\", info);\n        return NO;\n    }\n\n    // The `self` of the block will be the AspectInfo. Optional.\n    if (numberOfArguments > 1) {\n        [blockInvocation setArgument:&info atIndex:1];\n    }\n    \n\tvoid *argBuf = NULL;\n    for (NSUInteger idx = 2; idx < numberOfArguments; idx++) {\n        const char *type = [originalInvocation.methodSignature getArgumentTypeAtIndex:idx];\n\t\tNSUInteger argSize;\n\t\tNSGetSizeAndAlignment(type, &argSize, NULL);\n        \n\t\tif (!(argBuf = reallocf(argBuf, argSize))) {\n            AspectLogError(@\"Failed to allocate memory for block invocation.\");\n\t\t\treturn NO;\n\t\t}\n        \n\t\t[originalInvocation getArgument:argBuf atIndex:idx];\n\t\t[blockInvocation setArgument:argBuf atIndex:idx];\n    }\n    \n    [blockInvocation invokeWithTarget:self.block];\n    \n    if (argBuf != NULL) {\n        free(argBuf);\n    }\n    return YES;\n}\n\n- (NSString *)description {\n    return [NSString stringWithFormat:@\"<%@: %p, SEL:%@ object:%@ options:%tu block:%@ (#%tu args)>\", self.class, self, NSStringFromSelector(self.selector), self.object, self.options, self.block, self.blockSignature.numberOfArguments];\n}\n\n- (BOOL)remove {\n    return aspect_remove(self, NULL);\n}\n\n@end\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - AspectsContainer\n\n@implementation AspectsContainer\n\n- (BOOL)hasAspects {\n    return self.beforeAspects.count > 0 || self.insteadAspects.count > 0 || self.afterAspects.count > 0;\n}\n\n- (void)addAspect:(AspectIdentifier *)aspect withOptions:(AspectOptions)options {\n    NSParameterAssert(aspect);\n    NSUInteger position = options&AspectPositionFilter;\n    switch (position) {\n        case AspectPositionBefore:  self.beforeAspects  = [(self.beforeAspects ?:@[]) arrayByAddingObject:aspect]; break;\n        case AspectPositionInstead: self.insteadAspects = [(self.insteadAspects?:@[]) arrayByAddingObject:aspect]; break;\n        case AspectPositionAfter:   self.afterAspects   = [(self.afterAspects  ?:@[]) arrayByAddingObject:aspect]; break;\n    }\n}\n\n- (BOOL)removeAspect:(id)aspect {\n    for (NSString *aspectArrayName in @[NSStringFromSelector(@selector(beforeAspects)),\n                                        NSStringFromSelector(@selector(insteadAspects)),\n                                        NSStringFromSelector(@selector(afterAspects))]) {\n        NSArray *array = [self valueForKey:aspectArrayName];\n        NSUInteger index = [array indexOfObjectIdenticalTo:aspect];\n        if (array && index != NSNotFound) {\n            NSMutableArray *newArray = [NSMutableArray arrayWithArray:array];\n            [newArray removeObjectAtIndex:index];\n            [self setValue:newArray forKey:aspectArrayName];\n            return YES;\n        }\n    }\n    return NO;\n}\n\n- (NSString *)description {\n    return [NSString stringWithFormat:@\"<%@: %p, before:%@, instead:%@, after:%@>\", self.class, self, self.beforeAspects, self.insteadAspects, self.afterAspects];\n}\n\n@end\n\n///////////////////////////////////////////////////////////////////////////////////////////\n#pragma mark - AspectInfo\n\n@implementation AspectInfo\n\n@synthesize arguments = _arguments;\n\n- (id)initWithInstance:(__unsafe_unretained id)instance invocation:(NSInvocation *)invocation {\n    NSCParameterAssert(instance);\n    NSCParameterAssert(invocation);\n    if (self = [super init]) {\n        _instance = instance;\n        _originalInvocation = invocation;\n    }\n    return self;\n}\n\n- (NSArray *)arguments {\n    // Lazily evaluate arguments, boxing is expensive.\n    if (!_arguments) {\n        _arguments = self.originalInvocation.aspects_arguments;\n    }\n    return _arguments;\n}\n\n@end\n"
  },
  {
    "path": "States.sketchplugin/Contents/Resources/States.bundle/Contents/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BuildMachineOSBuild</key>\n\t<string>15G31</string>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>States</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.edenvidal.states-for-sketch</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>States</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleSupportedPlatforms</key>\n\t<array>\n\t\t<string>MacOSX</string>\n\t</array>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>DTCompiler</key>\n\t<string>com.apple.compilers.llvm.clang.1_0</string>\n\t<key>DTPlatformBuild</key>\n\t<string>7D1014</string>\n\t<key>DTPlatformVersion</key>\n\t<string>GM</string>\n\t<key>DTSDKBuild</key>\n\t<string>15E60</string>\n\t<key>DTSDKName</key>\n\t<string>macosx10.11</string>\n\t<key>DTXcode</key>\n\t<string>0731</string>\n\t<key>DTXcodeBuild</key>\n\t<string>7D1014</string>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2016 Eden Vidal. All rights reserved.</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "States.sketchplugin/Contents/Resources/States.bundle/Contents/_CodeSignature/CodeResources",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t\t<key>Resources/StatesWindow.nib</key>\n\t\t<data>\n\t\ttPNG8G23xzx2FF9fJkMeLlowPCg=\n\t\t</data>\n\t\t<key>Resources/dirty.tiff</key>\n\t\t<data>\n\t\tOigIS04hpst041DCQF9TZTP28HM=\n\t\t</data>\n\t</dict>\n\t<key>files2</key>\n\t<dict>\n\t\t<key>Resources/StatesWindow.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\ttPNG8G23xzx2FF9fJkMeLlowPCg=\n\t\t\t</data>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\tR+X7XpAk5/v35Io50Z1VeFKd+JD0rIEYCGO62q9luas=\n\t\t\t</data>\n\t\t</dict>\n\t\t<key>Resources/dirty.tiff</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\tOigIS04hpst041DCQF9TZTP28HM=\n\t\t\t</data>\n\t\t\t<key>hash2</key>\n\t\t\t<data>\n\t\t\t7KCD71Cxnh0qc7BUXhpJv/M2LHesZc1jZI4/QyOsTC0=\n\t\t\t</data>\n\t\t</dict>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^Resources/</key>\n\t\t<true/>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^Resources/.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^[^/]+$</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "States.sketchplugin/Contents/Sketch/lib/runtime.js",
    "content": "// runtime.js\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n(function(){\n\tthis.runtime = {};\n\t/// This function fetches the plugin path from a current script path\n\tthis.runtime.pluginPath = function()\n\t{\n\t\tvar result = [NSString stringWithString: coscript.env().scriptURL.path()];\n\t\twhile(result.lastPathComponent().pathExtension() != \"sketchplugin\"){\n\t\t\tresult = result.stringByDeletingLastPathComponent();\n\t\t}\n\t\treturn result;\n\t}\n\t/// This function loads a bundle with the given name located in Resources directory\n \t/// of this plugin\n \tthis.runtime.loadBundle = function(bundleName)\n\t{\n\t\tvar bundlePath = runtime.pluginPath() + \"/Contents/Resources/\" + bundleName;\n\t\tvar bundle = [NSBundle bundleWithPath: bundlePath];\n\t\tbundle.load();\n\t}\n})();\n"
  },
  {
    "path": "States.sketchplugin/Contents/Sketch/manifest.json",
    "content": "{\n\t\"name\": \"States\",\n\t\"description\": \"Create different artboard states and switch between them easily\",\n\t\"author\": \"Eden Vidal\",\n\t\"homepage\": \"http://edenvidal.com\",\n\t\"version\": \"1.0.0\",\n\t\"identifier\": \"com.edenvidal.states-for-sketch\",\n\t\"compatibleVersion\": 3,\n\t\"bundleVersion\": 1,\n\t\"commands\": [{\n\t\t\"name\": \"Show States\",\n\t\t\"identifier\": \"show-states\",\n\t\t\"script\": \"plugin.js\",\n\t\t\"handler\": \"showStatesWindow\"\n\t\t}],\n\t\"menu\": {\n\t\t\"items\": [\"show-states\"],\n\t\t\"isRoot\": true\n\t}\n}\n"
  },
  {
    "path": "States.sketchplugin/Contents/Sketch/plugin.js",
    "content": "// plugin.js\n// Copyright (c) 2016 Eden Vidal\n//\n// This software may be modified and distributed under the terms\n// of the MIT license.  See the LICENSE file for details.\n\n@import \"lib/runtime.js\"\n\nfunction showStatesWindow(context)\n{\n\tif (NSClassFromString(\"STStatesController\") == null) {\n\t\truntime.loadBundle(\"States.bundle\");\n\t\t[STSketch setPluginContextDictionary: context];\n\t}\n\n\tvar controller = [StatesController defaultController];\n\tif ([[controller window] isVisible]) {\n\t\t[[controller window] close];\n\t} else {\n\t\t[controller showWindow: nil];\n\t}\n    [STSketch toggleStatesPluginName];\n}\n"
  },
  {
    "path": "css/normalize.css",
    "content": "/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n/**\n * 1. Set default font family to sans-serif.\n * 2. Prevent iOS and IE text size adjust after device orientation change,\n *    without disabling user zoom.\n */\nhtml {\n  font-family: sans-serif;\n  /* 1 */\n  -ms-text-size-adjust: 100%;\n  /* 2 */\n  -webkit-text-size-adjust: 100%;\n  /* 2 */\n}\n/**\n * Remove default margin.\n */\nbody {\n  margin: 0;\n}\n/* HTML5 display definitions\n   ========================================================================== */\n/**\n * Correct `block` display not defined for any HTML5 element in IE 8/9.\n * Correct `block` display not defined for `details` or `summary` in IE 10/11\n * and Firefox.\n * Correct `block` display not defined for `main` in IE 11.\n */\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n  display: block;\n}\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block;\n  /* 1 */\n  vertical-align: baseline;\n  /* 2 */\n}\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n/**\n * Address `[hidden]` styling not present in IE 8/9/10.\n * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n */\n[hidden],\ntemplate {\n  display: none;\n}\n/* Links\n   ========================================================================== */\n/**\n * Remove the gray background color from active links in IE 10.\n */\na {\n  background-color: transparent;\n}\n/**\n * Improve readability of focused elements when they are also in an\n * active/hover state.\n */\na:active,\na:hover {\n  outline: 0;\n}\n/* Text-level semantics\n   ========================================================================== */\n/**\n * Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n */\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n/**\n * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n */\nb,\nstrong {\n  font-weight: bold;\n}\n/**\n * Address styling not present in Safari and Chrome.\n */\ndfn {\n  font-style: italic;\n}\n/**\n * Address variable `h1` font-size and margin within `section` and `article`\n * contexts in Firefox 4+, Safari, and Chrome.\n */\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n/**\n * Address styling not present in IE 8/9.\n */\nmark {\n  background: #ff0;\n  color: #000;\n}\n/**\n * Address inconsistent and variable font size in all browsers.\n */\nsmall {\n  font-size: 80%;\n}\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\nsup {\n  top: -0.5em;\n}\nsub {\n  bottom: -0.25em;\n}\n/* Embedded content\n   ========================================================================== */\n/**\n * Remove border when inside `a` element in IE 8/9/10.\n */\nimg {\n  border: 0;\n}\n/**\n * Correct overflow not hidden in IE 9/10/11.\n */\nsvg:not(:root) {\n  overflow: hidden;\n}\n/* Grouping content\n   ========================================================================== */\n/**\n * Address margin not present in IE 8/9 and Safari.\n */\nfigure {\n  margin: 1em 40px;\n}\n/**\n * Address differences between Firefox and other browsers.\n */\nhr {\n  box-sizing: content-box;\n  height: 0;\n}\n/**\n * Contain overflow in all browsers.\n */\npre {\n  overflow: auto;\n}\n/**\n * Address odd `em`-unit font size rendering in all browsers.\n */\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n/* Forms\n   ========================================================================== */\n/**\n * Known limitation: by default, Chrome and Safari on OS X allow very limited\n * styling of `select`, unless a `border` property is set.\n */\n/**\n * 1. Correct color not being inherited.\n *    Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n */\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit;\n  /* 1 */\n  font: inherit;\n  /* 2 */\n  margin: 0;\n  /* 3 */\n}\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10/11.\n */\nbutton {\n  overflow: visible;\n}\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n * Correct `select` style inheritance in Firefox.\n */\nbutton,\nselect {\n  text-transform: none;\n}\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n *    and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n *    `input` and others.\n * 4. CUSTOM FOR WEBFLOW: Removed the input[type=\"submit\"] selector to reduce\n *    specificity and defer to the .w-button selector\n */\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"] {\n  -webkit-appearance: button;\n  /* 2 */\n  cursor: pointer;\n  /* 3 */\n}\n/**\n * Re-set default cursor for disabled elements.\n */\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n/**\n * Remove inner padding and border in Firefox 4+.\n */\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\ninput {\n  line-height: normal;\n}\n/**\n * It's recommended that you don't attempt to style these elements.\n * Firefox's implementation doesn't respect box-sizing, padding, or width.\n *\n * 1. Address box sizing set to `content-box` in IE 8/9/10.\n * 2. Remove excess padding in IE 8/9/10.\n */\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box;\n  /* 1 */\n  padding: 0;\n  /* 2 */\n}\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n/**\n * 1. CUSTOM FOR WEBFLOW: changed from `textfield` to `none` to normalize iOS rounded input\n * 2. CUSTOM FOR WEBFLOW: box-sizing: content-box rule removed\n *    (similar to normalize.css >=4.0.0)\n */\ninput[type=\"search\"] {\n  -webkit-appearance: none;\n  /* 1 */\n}\n/**\n * Remove inner padding and search cancel button in Safari and Chrome on OS X.\n * Safari (but not Chrome) clips the cancel button when the search input has\n * padding (and `textfield` appearance).\n */\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n/**\n * Define consistent border, margin, and padding.\n */\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n/**\n * 1. Correct `color` not being inherited in IE 8/9/10/11.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\nlegend {\n  border: 0;\n  /* 1 */\n  padding: 0;\n  /* 2 */\n}\n/**\n * Remove default vertical scrollbar in IE 8/9/10/11.\n */\ntextarea {\n  overflow: auto;\n}\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\noptgroup {\n  font-weight: bold;\n}\n/* Tables\n   ========================================================================== */\n/**\n * Remove most spacing between table cells.\n */\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\ntd,\nth {\n  padding: 0;\n}\n"
  },
  {
    "path": "css/states.webflow.css",
    "content": "body {\n  background-color: #f2f2f2;\n  color: #333;\n  font-size: 16px;\n  line-height: 20px;\n}\n\nh1 {\n  margin-top: 20px;\n  font-size: 74px;\n  line-height: 72px;\n  font-weight: 400;\n}\n\nh2 {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  font-family: 'Playfair Display', sans-serif;\n  font-size: 23px;\n  line-height: 32px;\n  font-weight: 400;\n  letter-spacing: 0.2px;\n}\n\nh3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n  font-family: 'Playfair Display', sans-serif;\n  font-size: 24px;\n  line-height: 30px;\n}\n\nh5 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n  font-family: 'Playfair Display', sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  font-style: italic;\n  font-weight: 400;\n}\n\np {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  color: rgba(0, 0, 0, .5);\n}\n\na {\n  clear: left;\n  color: #fff;\n  text-decoration: underline;\n}\n\nimg {\n  display: inline-block;\n  max-width: 100%;\n}\n\n.section {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  height: 100vh;\n  padding: 8%;\n  -webkit-box-orient: horizontal;\n  -webkit-box-direction: normal;\n  -webkit-flex-direction: row;\n  -ms-flex-direction: row;\n  flex-direction: row;\n  -webkit-justify-content: space-around;\n  -ms-flex-pack: distribute;\n  justify-content: space-around;\n  -webkit-flex-wrap: nowrap;\n  -ms-flex-wrap: nowrap;\n  flex-wrap: nowrap;\n  -webkit-box-align: stretch;\n  -webkit-align-items: stretch;\n  -ms-flex-align: stretch;\n  align-items: stretch;\n  -webkit-align-content: center;\n  -ms-flex-line-pack: center;\n  align-content: center;\n  font-weight: 400;\n}\n\n.section.black {\n  background-color: #000;\n}\n\n.section.black.bg {\n  background-color: #000;\n  background-image: -webkit-linear-gradient(270deg, transparent, rgba(0, 0, 0, .5) 80%, #000), url('../images/mate.gif');\n  background-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, .5) 80%, #000), url('../images/mate.gif');\n  background-position: 0px 0px, 50% 50%;\n  background-repeat: repeat, no-repeat;\n  background-attachment: scroll, fixed;\n}\n\n.section.black.bg2 {\n  background-image: -webkit-linear-gradient(90deg, transparent, #000), url('../images/mate.gif');\n  background-image: linear-gradient(0deg, transparent, #000), url('../images/mate.gif');\n  background-position: 0px 0px, 50% 50%;\n  background-repeat: repeat, no-repeat;\n  background-attachment: scroll, fixed;\n}\n\n.section.artboard {\n  background-image: url('../images/Animation2.gif');\n  background-position: 50% 50%;\n  background-repeat: no-repeat;\n  background-attachment: fixed;\n}\n\n._33 {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  height: 100%;\n  -webkit-box-orient: vertical;\n  -webkit-box-direction: normal;\n  -webkit-flex-direction: column;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n  -ms-flex-pack: center;\n  justify-content: center;\n  -webkit-flex-wrap: nowrap;\n  -ms-flex-wrap: nowrap;\n  flex-wrap: nowrap;\n  -webkit-box-align: start;\n  -webkit-align-items: flex-start;\n  -ms-flex-align: start;\n  align-items: flex-start;\n  -webkit-align-content: flex-start;\n  -ms-flex-line-pack: start;\n  align-content: flex-start;\n  -webkit-box-flex: 1;\n  -webkit-flex: 1;\n  -ms-flex: 1;\n  flex: 1;\n}\n\n.button {\n  border: 5px solid #000;\n  background-color: transparent;\n  color: #000;\n  font-size: 18px;\n}\n\n.button.white {\n  padding: 9px 15px;\n  border-color: #fff;\n  color: #fff;\n}\n\n.white {\n  color: #fff;\n  font-weight: 400;\n}\n\n.white.bold {\n  font-weight: 700;\n}\n\n.white.space {\n  margin-bottom: 36px;\n}\n\n.bold {\n  color: #fff;\n  font-weight: 400;\n}\n\n._75 {\n  width: 75%;\n  -webkit-align-self: center;\n  -ms-flex-item-align: center;\n  align-self: center;\n}\n\n._25 {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  width: 25%;\n  -webkit-box-orient: vertical;\n  -webkit-box-direction: normal;\n  -webkit-flex-direction: column;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  -webkit-box-align: start;\n  -webkit-align-items: flex-start;\n  -ms-flex-align: start;\n  align-items: flex-start;\n  -webkit-align-self: center;\n  -ms-flex-item-align: center;\n  align-self: center;\n}\n\n._25.bottom {\n  -webkit-align-self: flex-end;\n  -ms-flex-item-align: end;\n  align-self: flex-end;\n}\n\n._25.long {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-orient: vertical;\n  -webkit-box-direction: normal;\n  -webkit-flex-direction: column;\n  -ms-flex-direction: column;\n  flex-direction: column;\n  -webkit-box-pack: justify;\n  -webkit-justify-content: space-between;\n  -ms-flex-pack: justify;\n  justify-content: space-between;\n  -webkit-align-self: stretch;\n  -ms-flex-item-align: stretch;\n  align-self: stretch;\n}\n\n.social {\n  position: fixed;\n  top: 0px;\n  right: 0px;\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  padding: 25px;\n  opacity: 0.5;\n  -webkit-transition: opacity 200ms ease;\n  transition: opacity 200ms ease;\n}\n\n.social:hover {\n  opacity: 1;\n}\n\n.icon {\n  margin-right: 25px;\n}\n\n._50 {\n  -webkit-align-self: flex-end;\n  -ms-flex-item-align: end;\n  align-self: flex-end;\n  -webkit-flex-basis: 50%;\n  -ms-flex-preferred-size: 50%;\n  flex-basis: 50%;\n  text-align: center;\n}\n\n.center {\n  float: none;\n  text-align: center;\n}\n\n.red {\n  background-color: red;\n}\n\n.link {\n  color: #000;\n}\n\n.link-2 {\n  border-bottom: 1px solid #000;\n}\n\n.none {\n  margin-bottom: 20px;\n  text-decoration: none;\n}\n\nhtml.w-mod-js *[data-ix=\"display-none\"] {\n  display: none;\n}\n\n@media (max-width: 991px) {\n  .section {\n    height: 100%;\n    -webkit-box-orient: vertical;\n    -webkit-box-direction: normal;\n    -webkit-flex-direction: column;\n    -ms-flex-direction: column;\n    flex-direction: column;\n  }\n  .section.artboard {\n    background-image: none;\n    background-position: 0px 0px;\n    background-repeat: repeat;\n    background-attachment: scroll;\n  }\n  ._75 {\n    width: 100%;\n  }\n  ._25 {\n    width: 100%;\n  }\n  ._25.bottom {\n    margin-bottom: 5%;\n  }\n}\n\n"
  },
  {
    "path": "css/webflow.css",
    "content": "@font-face {\n  font-family: 'webflow-icons';\n  src: url(\"data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBiUAAAC8AAAAYGNtYXDpP+a4AAABHAAAAFxnYXNwAAAAEAAAAXgAAAAIZ2x5ZmhS2XEAAAGAAAADHGhlYWQTFw3HAAAEnAAAADZoaGVhCXYFgQAABNQAAAAkaG10eCe4A1oAAAT4AAAAMGxvY2EDtALGAAAFKAAAABptYXhwABAAPgAABUQAAAAgbmFtZSoCsMsAAAVkAAABznBvc3QAAwAAAAAHNAAAACAAAwP4AZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpAwPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAQAAAAAwACAACAAQAAQAg5gPpA//9//8AAAAAACDmAOkA//3//wAB/+MaBBcIAAMAAQAAAAAAAAAAAAAAAAABAAH//wAPAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEBIAAAAyADgAAFAAAJAQcJARcDIP5AQAGA/oBAAcABwED+gP6AQAABAOAAAALgA4AABQAAEwEXCQEH4AHAQP6AAYBAAcABwED+gP6AQAAAAwDAAOADQALAAA8AHwAvAAABISIGHQEUFjMhMjY9ATQmByEiBh0BFBYzITI2PQE0JgchIgYdARQWMyEyNj0BNCYDIP3ADRMTDQJADRMTDf3ADRMTDQJADRMTDf3ADRMTDQJADRMTAsATDSANExMNIA0TwBMNIA0TEw0gDRPAEw0gDRMTDSANEwAAAAABAJ0AtAOBApUABQAACQIHCQEDJP7r/upcAXEBcgKU/usBFVz+fAGEAAAAAAL//f+9BAMDwwAEAAkAABcBJwEXAwE3AQdpA5ps/GZsbAOabPxmbEMDmmz8ZmwDmvxmbAOabAAAAgAA/8AEAAPAAB0AOwAABSInLgEnJjU0Nz4BNzYzMTIXHgEXFhUUBw4BBwYjNTI3PgE3NjU0Jy4BJyYjMSIHDgEHBhUUFx4BFxYzAgBqXV6LKCgoKIteXWpqXV6LKCgoKIteXWpVSktvICEhIG9LSlVVSktvICEhIG9LSlVAKCiLXl1qal1eiygoKCiLXl1qal1eiygoZiEgb0tKVVVKS28gISEgb0tKVVVKS28gIQABAAABwAIAA8AAEgAAEzQ3PgE3NjMxFSIHDgEHBhUxIwAoKIteXWpVSktvICFmAcBqXV6LKChmISBvS0pVAAAAAgAA/8AFtgPAADIAOgAAARYXHgEXFhUUBw4BBwYHIxUhIicuAScmNTQ3PgE3NjMxOAExNDc+ATc2MzIXHgEXFhcVATMJATMVMzUEjD83NlAXFxYXTjU1PQL8kz01Nk8XFxcXTzY1PSIjd1BQWlJJSXInJw3+mdv+2/7c25MCUQYcHFg5OUA/ODlXHBwIAhcXTzY1PTw1Nk8XF1tQUHcjIhwcYUNDTgL+3QFt/pOTkwABAAAAAQAAmM7nP18PPPUACwQAAAAAANciZKUAAAAA1yJkpf/9/70FtgPDAAAACAACAAAAAAAAAAEAAAPA/8AAAAW3//3//QW2AAEAAAAAAAAAAAAAAAAAAAAMBAAAAAAAAAAAAAAAAgAAAAQAASAEAADgBAAAwAQAAJ0EAP/9BAAAAAQAAAAFtwAAAAAAAAAKABQAHgAyAEYAjACiAL4BFgE2AY4AAAABAAAADAA8AAMAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEADQAAAAEAAAAAAAIABwCWAAEAAAAAAAMADQBIAAEAAAAAAAQADQCrAAEAAAAAAAUACwAnAAEAAAAAAAYADQBvAAEAAAAAAAoAGgDSAAMAAQQJAAEAGgANAAMAAQQJAAIADgCdAAMAAQQJAAMAGgBVAAMAAQQJAAQAGgC4AAMAAQQJAAUAFgAyAAMAAQQJAAYAGgB8AAMAAQQJAAoANADsd2ViZmxvdy1pY29ucwB3AGUAYgBmAGwAbwB3AC0AaQBjAG8AbgBzVmVyc2lvbiAxLjAAVgBlAHIAcwBpAG8AbgAgADEALgAwd2ViZmxvdy1pY29ucwB3AGUAYgBmAGwAbwB3AC0AaQBjAG8AbgBzd2ViZmxvdy1pY29ucwB3AGUAYgBmAGwAbwB3AC0AaQBjAG8AbgBzUmVndWxhcgBSAGUAZwB1AGwAYQByd2ViZmxvdy1pY29ucwB3AGUAYgBmAGwAbwB3AC0AaQBjAG8AbgBzRm9udCBnZW5lcmF0ZWQgYnkgSWNvTW9vbi4ARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\") format('truetype');\n  font-weight: normal;\n  font-style: normal;\n}\n[class^=\"w-icon-\"],\n[class*=\" w-icon-\"] {\n  /* use !important to prevent issues with browser extensions that change fonts */\n  font-family: 'webflow-icons' !important;\n  speak: none;\n  font-style: normal;\n  font-weight: normal;\n  font-variant: normal;\n  text-transform: none;\n  line-height: 1;\n  /* Better Font Rendering =========== */\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n.w-icon-slider-right:before {\n  content: \"\\e600\";\n}\n.w-icon-slider-left:before {\n  content: \"\\e601\";\n}\n.w-icon-nav-menu:before {\n  content: \"\\e602\";\n}\n.w-icon-arrow-down:before,\n.w-icon-dropdown-toggle:before {\n  content: \"\\e603\";\n}\n.w-icon-file-upload-remove:before {\n  content: \"\\e900\";\n}\n.w-icon-file-upload-icon:before {\n  content: \"\\e903\";\n}\n* {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\nhtml {\n  height: 100%;\n}\nbody {\n  margin: 0;\n  min-height: 100%;\n  background-color: #fff;\n  font-family: Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333;\n}\nimg {\n  max-width: 100%;\n  vertical-align: middle;\n  display: inline-block;\n}\nhtml.w-mod-touch * {\n  background-attachment: scroll !important;\n}\n.w-block {\n  display: block;\n}\n.w-inline-block {\n  max-width: 100%;\n  display: inline-block;\n}\n.w-clearfix:before,\n.w-clearfix:after {\n  content: \" \";\n  display: table;\n}\n.w-clearfix:after {\n  clear: both;\n}\n.w-hidden {\n  display: none;\n}\n.w-button {\n  display: inline-block;\n  padding: 9px 15px;\n  background-color: #3898EC;\n  color: white;\n  border: 0;\n  line-height: inherit;\n  text-decoration: none;\n  cursor: pointer;\n  border-radius: 0;\n}\ninput.w-button {\n  -webkit-appearance: button;\n}\nhtml[data-w-dynpage] [data-w-cloak] {\n  color: transparent !important;\n}\n.w-webflow-badge,\n.w-webflow-badge * {\n  position: static;\n  left: auto;\n  top: auto;\n  right: auto;\n  bottom: auto;\n  z-index: auto;\n  display: block;\n  visibility: visible;\n  overflow: visible;\n  overflow-x: visible;\n  overflow-y: visible;\n  box-sizing: border-box;\n  width: auto;\n  height: auto;\n  max-height: none;\n  max-width: none;\n  min-height: 0;\n  min-width: 0;\n  margin: 0;\n  padding: 0;\n  float: none;\n  clear: none;\n  border: 0 none transparent;\n  border-radius: 0;\n  background: none;\n  background-image: none;\n  background-position: 0% 0%;\n  background-size: auto auto;\n  background-repeat: repeat;\n  background-origin: padding-box;\n  background-clip: border-box;\n  background-attachment: scroll;\n  background-color: transparent;\n  box-shadow: none;\n  opacity: 1.0;\n  transform: none;\n  transition: none;\n  direction: ltr;\n  font-family: inherit;\n  font-weight: inherit;\n  color: inherit;\n  font-size: inherit;\n  line-height: inherit;\n  font-style: inherit;\n  font-variant: inherit;\n  text-align: inherit;\n  letter-spacing: inherit;\n  text-decoration: inherit;\n  text-indent: 0;\n  text-transform: inherit;\n  list-style-type: disc;\n  text-shadow: none;\n  font-smoothing: auto;\n  vertical-align: baseline;\n  cursor: inherit;\n  white-space: inherit;\n  word-break: normal;\n  word-spacing: normal;\n  word-wrap: normal;\n}\n.w-webflow-badge {\n  position: fixed !important;\n  display: inline-block !important;\n  visibility: visible !important;\n  opacity: 1 !important;\n  z-index: 2147483647 !important;\n  top: auto !important;\n  right: 12px !important;\n  bottom: 12px !important;\n  left: auto !important;\n  color: #AAADB0 !important;\n  background-color: #fff !important;\n  border-radius: 3px !important;\n  padding: 6px 8px 6px 6px !important;\n  font-size: 12px !important;\n  opacity: 1.0 !important;\n  line-height: 14px !important;\n  text-decoration: none !important;\n  transform: none !important;\n  margin: 0 !important;\n  width: auto !important;\n  height: auto !important;\n  overflow: visible !important;\n  white-space: nowrap;\n  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0px 1px 3px rgba(0, 0, 0, 0.1);\n}\n.w-webflow-badge > img {\n  display: inline-block !important;\n  visibility: visible !important;\n  opacity: 1 !important;\n  vertical-align: middle !important;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  font-weight: bold;\n  margin-bottom: 10px;\n}\nh1 {\n  font-size: 38px;\n  line-height: 44px;\n  margin-top: 20px;\n}\nh2 {\n  font-size: 32px;\n  line-height: 36px;\n  margin-top: 20px;\n}\nh3 {\n  font-size: 24px;\n  line-height: 30px;\n  margin-top: 20px;\n}\nh4 {\n  font-size: 18px;\n  line-height: 24px;\n  margin-top: 10px;\n}\nh5 {\n  font-size: 14px;\n  line-height: 20px;\n  margin-top: 10px;\n}\nh6 {\n  font-size: 12px;\n  line-height: 18px;\n  margin-top: 10px;\n}\np {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\nblockquote {\n  margin: 0 0 10px 0;\n  padding: 10px 20px;\n  border-left: 5px solid #E2E2E2;\n  font-size: 18px;\n  line-height: 22px;\n}\nfigure {\n  margin: 0;\n  margin-bottom: 10px;\n}\nfigcaption {\n  margin-top: 5px;\n  text-align: center;\n}\nul,\nol {\n  margin-top: 0px;\n  margin-bottom: 10px;\n  padding-left: 40px;\n}\n.w-list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n.w-embed:before,\n.w-embed:after {\n  content: \" \";\n  display: table;\n}\n.w-embed:after {\n  clear: both;\n}\n.w-video {\n  width: 100%;\n  position: relative;\n  padding: 0;\n}\n.w-video iframe,\n.w-video object,\n.w-video embed {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"] {\n  border: 0;\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n.w-form {\n  margin: 0 0 15px;\n}\n.w-form-done {\n  display: none;\n  padding: 20px;\n  text-align: center;\n  background-color: #dddddd;\n}\n.w-form-fail {\n  display: none;\n  margin-top: 10px;\n  padding: 10px;\n  background-color: #ffdede;\n}\nlabel {\n  display: block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n.w-input,\n.w-select {\n  display: block;\n  width: 100%;\n  height: 38px;\n  padding: 8px 12px;\n  margin-bottom: 10px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #333333;\n  vertical-align: middle;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n}\n.w-input:-moz-placeholder,\n.w-select:-moz-placeholder {\n  color: #999;\n}\n.w-input::-moz-placeholder,\n.w-select::-moz-placeholder {\n  color: #999;\n  opacity: 1;\n}\n.w-input:-ms-input-placeholder,\n.w-select:-ms-input-placeholder {\n  color: #999;\n}\n.w-input::-webkit-input-placeholder,\n.w-select::-webkit-input-placeholder {\n  color: #999;\n}\n.w-input:focus,\n.w-select:focus {\n  border-color: #3898EC;\n  outline: 0;\n}\n.w-input[disabled],\n.w-select[disabled],\n.w-input[readonly],\n.w-select[readonly],\nfieldset[disabled] .w-input,\nfieldset[disabled] .w-select {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\ntextarea.w-input,\ntextarea.w-select {\n  height: auto;\n}\n.w-select {\n  background-image: -webkit-linear-gradient(white 0%, #f3f3f3 100%);\n  background-image: linear-gradient(white 0%, #f3f3f3 100%);\n}\n.w-select[multiple] {\n  height: auto;\n}\n.w-form-label {\n  display: inline-block;\n  cursor: pointer;\n  font-weight: normal;\n  margin-bottom: 0px;\n}\n.w-checkbox,\n.w-radio {\n  display: block;\n  margin-bottom: 5px;\n  padding-left: 20px;\n}\n.w-checkbox:before,\n.w-radio:before,\n.w-checkbox:after,\n.w-radio:after {\n  content: \" \";\n  display: table;\n}\n.w-checkbox:after,\n.w-radio:after {\n  clear: both;\n}\n.w-checkbox-input,\n.w-radio-input {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  line-height: normal;\n  float: left;\n  margin-left: -20px;\n}\n.w-radio-input {\n  margin-top: 3px;\n}\n.w-file-upload {\n  display: block;\n  margin-bottom: 10px;\n}\n.w-file-upload-input {\n  width: 0.1px;\n  height: 0.1px;\n  opacity: 0;\n  overflow: hidden;\n  position: absolute;\n  z-index: -100;\n}\n.w-file-upload-default,\n.w-file-upload-uploading,\n.w-file-upload-success {\n  display: inline-block;\n  color: #333333;\n}\n.w-file-upload-error {\n  display: block;\n  margin-top: 10px;\n}\n.w-file-upload-default.w-hidden,\n.w-file-upload-uploading.w-hidden,\n.w-file-upload-error.w-hidden,\n.w-file-upload-success.w-hidden {\n  display: none;\n}\n.w-file-upload-uploading-btn {\n  display: flex;\n  font-size: 14px;\n  font-weight: normal;\n  cursor: pointer;\n  margin: 0;\n  padding: 8px 12px;\n  border: 1px solid #cccccc;\n  background-color: #fafafa;\n}\n.w-file-upload-uploading-bg-img {\n  display: inline-block;\n  padding-left: 40px;\n  background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAzMCI+PHBhdGggZmlsbD0iY3VycmVudENvbG9yIiBvcGFjaXR5PSIuMiIgZD0iTTE1IDMwYTE1IDE1IDAgMSAxIDAtMzAgMTUgMTUgMCAwIDEgMCAzMHptMC0zYTEyIDEyIDAgMSAwIDAtMjQgMTIgMTIgMCAwIDAgMCAyNHoiLz48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIG9wYWNpdHk9Ii43NSIgZD0iTTAgMTVBMTUgMTUgMCAwIDEgMTUgMHYzQTEyIDEyIDAgMCAwIDMgMTVIMHoiPjxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgYXR0cmlidXRlVHlwZT0iWE1MIiBkdXI9IjAuNnMiIGZyb209IjAgMTUgMTUiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiB0bz0iMzYwIDE1IDE1IiB0eXBlPSJyb3RhdGUiLz48L3BhdGg+PC9zdmc+\");\n  background-position: 12px 50%;\n  background-size: 20px 20px;\n  background-repeat: no-repeat;\n}\n.w-file-upload-file {\n  display: flex;\n  flex-grow: 1;\n  justify-content: space-between;\n  margin: 0;\n  padding: 8px 9px 8px 11px;\n  border: 1px solid #cccccc;\n  background-color: #fafafa;\n}\n.w-file-upload-file-name {\n  font-size: 14px;\n  font-weight: normal;\n  display: block;\n}\n.w-file-remove-link {\n  margin-top: 3px;\n  margin-left: 10px;\n  width: auto;\n  height: auto;\n  padding: 3px;\n  display: block;\n  cursor: pointer;\n}\n.w-icon-file-upload-remove {\n  margin: auto;\n  font-size: 10px;\n}\n.w-file-upload-error-msg {\n  display: inline-block;\n  color: #ea384c;\n  padding: 2px 0;\n}\n.w-file-upload-info {\n  display: inline-block;\n  line-height: 38px;\n  padding: 0 12px;\n}\n.w-file-upload-label {\n  display: inline-block;\n  font-size: 14px;\n  font-weight: normal;\n  cursor: pointer;\n  margin: 0;\n  padding: 8px 12px;\n  border: 1px solid #cccccc;\n  background-color: #fafafa;\n}\n.w-file-upload-label-bg-img {\n  padding-left: 40px;\n  background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAxNCI+PHBhdGggZmlsbD0iY3VycmVudENvbG9yIiBkPSJNMTUuOTIgNS4wMmE0LjUgNC41IDAgMCAxIC4wOCA4Ljk1VjE0SDRhNCA0IDAgMSAxIDAtOCA2IDYgMCAwIDEgMTEuOTItLjk4ek0xMSA5aDNsLTQtNS00IDVoM3YyaDJWOXoiLz48L3N2Zz4=\");\n  background-position: 12px 50%;\n  background-size: 20px 20px;\n  background-repeat: no-repeat;\n}\n.w-icon-file-upload-icon,\n.w-icon-file-upload-uploading {\n  display: inline-block;\n  margin-right: 8px;\n  width: 20px;\n}\n.w-icon-file-upload-uploading {\n  height: 20px;\n}\n.w-container {\n  margin-left: auto;\n  margin-right: auto;\n  max-width: 940px;\n}\n.w-container:before,\n.w-container:after {\n  content: \" \";\n  display: table;\n}\n.w-container:after {\n  clear: both;\n}\n.w-container .w-row {\n  margin-left: -10px;\n  margin-right: -10px;\n}\n.w-row:before,\n.w-row:after {\n  content: \" \";\n  display: table;\n}\n.w-row:after {\n  clear: both;\n}\n.w-row .w-row {\n  margin-left: 0;\n  margin-right: 0;\n}\n.w-col {\n  position: relative;\n  float: left;\n  width: 100%;\n  min-height: 1px;\n  padding-left: 10px;\n  padding-right: 10px;\n}\n.w-col .w-col {\n  padding-left: 0;\n  padding-right: 0;\n}\n.w-col-1 {\n  width: 8.33333333%;\n}\n.w-col-2 {\n  width: 16.66666667%;\n}\n.w-col-3 {\n  width: 25%;\n}\n.w-col-4 {\n  width: 33.33333333%;\n}\n.w-col-5 {\n  width: 41.66666667%;\n}\n.w-col-6 {\n  width: 50%;\n}\n.w-col-7 {\n  width: 58.33333333%;\n}\n.w-col-8 {\n  width: 66.66666667%;\n}\n.w-col-9 {\n  width: 75%;\n}\n.w-col-10 {\n  width: 83.33333333%;\n}\n.w-col-11 {\n  width: 91.66666667%;\n}\n.w-col-12 {\n  width: 100%;\n}\n.w-hidden-main {\n  display: none !important;\n}\n@media screen and (max-width: 991px) {\n  .w-container {\n    max-width: 728px;\n  }\n  .w-hidden-main {\n    display: inherit !important;\n  }\n  .w-hidden-medium {\n    display: none !important;\n  }\n  .w-col-medium-1 {\n    width: 8.33333333%;\n  }\n  .w-col-medium-2 {\n    width: 16.66666667%;\n  }\n  .w-col-medium-3 {\n    width: 25%;\n  }\n  .w-col-medium-4 {\n    width: 33.33333333%;\n  }\n  .w-col-medium-5 {\n    width: 41.66666667%;\n  }\n  .w-col-medium-6 {\n    width: 50%;\n  }\n  .w-col-medium-7 {\n    width: 58.33333333%;\n  }\n  .w-col-medium-8 {\n    width: 66.66666667%;\n  }\n  .w-col-medium-9 {\n    width: 75%;\n  }\n  .w-col-medium-10 {\n    width: 83.33333333%;\n  }\n  .w-col-medium-11 {\n    width: 91.66666667%;\n  }\n  .w-col-medium-12 {\n    width: 100%;\n  }\n  .w-col-stack {\n    width: 100%;\n    left: auto;\n    right: auto;\n  }\n}\n@media screen and (max-width: 767px) {\n  .w-hidden-main {\n    display: inherit !important;\n  }\n  .w-hidden-medium {\n    display: inherit !important;\n  }\n  .w-hidden-small {\n    display: none !important;\n  }\n  .w-row,\n  .w-container .w-row {\n    margin-left: 0;\n    margin-right: 0;\n  }\n  .w-col {\n    width: 100%;\n    left: auto;\n    right: auto;\n  }\n  .w-col-small-1 {\n    width: 8.33333333%;\n  }\n  .w-col-small-2 {\n    width: 16.66666667%;\n  }\n  .w-col-small-3 {\n    width: 25%;\n  }\n  .w-col-small-4 {\n    width: 33.33333333%;\n  }\n  .w-col-small-5 {\n    width: 41.66666667%;\n  }\n  .w-col-small-6 {\n    width: 50%;\n  }\n  .w-col-small-7 {\n    width: 58.33333333%;\n  }\n  .w-col-small-8 {\n    width: 66.66666667%;\n  }\n  .w-col-small-9 {\n    width: 75%;\n  }\n  .w-col-small-10 {\n    width: 83.33333333%;\n  }\n  .w-col-small-11 {\n    width: 91.66666667%;\n  }\n  .w-col-small-12 {\n    width: 100%;\n  }\n}\n@media screen and (max-width: 479px) {\n  .w-container {\n    max-width: none;\n  }\n  .w-hidden-main {\n    display: inherit !important;\n  }\n  .w-hidden-medium {\n    display: inherit !important;\n  }\n  .w-hidden-small {\n    display: inherit !important;\n  }\n  .w-hidden-tiny {\n    display: none !important;\n  }\n  .w-col {\n    width: 100%;\n  }\n  .w-col-tiny-1 {\n    width: 8.33333333%;\n  }\n  .w-col-tiny-2 {\n    width: 16.66666667%;\n  }\n  .w-col-tiny-3 {\n    width: 25%;\n  }\n  .w-col-tiny-4 {\n    width: 33.33333333%;\n  }\n  .w-col-tiny-5 {\n    width: 41.66666667%;\n  }\n  .w-col-tiny-6 {\n    width: 50%;\n  }\n  .w-col-tiny-7 {\n    width: 58.33333333%;\n  }\n  .w-col-tiny-8 {\n    width: 66.66666667%;\n  }\n  .w-col-tiny-9 {\n    width: 75%;\n  }\n  .w-col-tiny-10 {\n    width: 83.33333333%;\n  }\n  .w-col-tiny-11 {\n    width: 91.66666667%;\n  }\n  .w-col-tiny-12 {\n    width: 100%;\n  }\n}\n.w-widget {\n  position: relative;\n}\n.w-widget-map {\n  width: 100%;\n  height: 400px;\n}\n.w-widget-map label {\n  width: auto;\n  display: inline;\n}\n.w-widget-map img {\n  max-width: inherit;\n}\n.w-widget-map .gm-style-iw {\n  width: 90% !important;\n  height: auto !important;\n  top: 7px !important;\n  left: 6% !important;\n  display: inline;\n  text-align: center;\n  overflow: hidden;\n}\n.w-widget-map .gm-style-iw + div {\n  display: none;\n}\n.w-widget-twitter {\n  overflow: hidden;\n}\n.w-widget-twitter-count-shim {\n  display: inline-block;\n  vertical-align: top;\n  position: relative;\n  width: 28px;\n  height: 20px;\n  text-align: center;\n  background: white;\n  border: #758696 solid 1px;\n  border-radius: 3px;\n}\n.w-widget-twitter-count-shim * {\n  pointer-events: none;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n.w-widget-twitter-count-shim .w-widget-twitter-count-inner {\n  position: relative;\n  font-size: 15px;\n  line-height: 12px;\n  text-align: center;\n  color: #999;\n  font-family: serif;\n}\n.w-widget-twitter-count-shim .w-widget-twitter-count-clear {\n  position: relative;\n  display: block;\n}\n.w-widget-twitter-count-shim.w--large {\n  width: 36px;\n  height: 28px;\n  margin-left: 7px;\n}\n.w-widget-twitter-count-shim.w--large .w-widget-twitter-count-inner {\n  font-size: 18px;\n  line-height: 18px;\n}\n.w-widget-twitter-count-shim:not(.w--vertical) {\n  margin-left: 5px;\n  margin-right: 8px;\n}\n.w-widget-twitter-count-shim:not(.w--vertical).w--large {\n  margin-left: 6px;\n}\n.w-widget-twitter-count-shim:not(.w--vertical):before,\n.w-widget-twitter-count-shim:not(.w--vertical):after {\n  top: 50%;\n  left: 0;\n  border: solid transparent;\n  content: \" \";\n  height: 0;\n  width: 0;\n  position: absolute;\n  pointer-events: none;\n}\n.w-widget-twitter-count-shim:not(.w--vertical):before {\n  border-color: rgba(117, 134, 150, 0);\n  border-right-color: #5d6c7b;\n  border-width: 4px;\n  margin-left: -9px;\n  margin-top: -4px;\n}\n.w-widget-twitter-count-shim:not(.w--vertical).w--large:before {\n  border-width: 5px;\n  margin-left: -10px;\n  margin-top: -5px;\n}\n.w-widget-twitter-count-shim:not(.w--vertical):after {\n  border-color: rgba(255, 255, 255, 0);\n  border-right-color: white;\n  border-width: 4px;\n  margin-left: -8px;\n  margin-top: -4px;\n}\n.w-widget-twitter-count-shim:not(.w--vertical).w--large:after {\n  border-width: 5px;\n  margin-left: -9px;\n  margin-top: -5px;\n}\n.w-widget-twitter-count-shim.w--vertical {\n  width: 61px;\n  height: 33px;\n  margin-bottom: 8px;\n}\n.w-widget-twitter-count-shim.w--vertical:before,\n.w-widget-twitter-count-shim.w--vertical:after {\n  top: 100%;\n  left: 50%;\n  border: solid transparent;\n  content: \" \";\n  height: 0;\n  width: 0;\n  position: absolute;\n  pointer-events: none;\n}\n.w-widget-twitter-count-shim.w--vertical:before {\n  border-color: rgba(117, 134, 150, 0);\n  border-top-color: #5d6c7b;\n  border-width: 5px;\n  margin-left: -5px;\n}\n.w-widget-twitter-count-shim.w--vertical:after {\n  border-color: rgba(255, 255, 255, 0);\n  border-top-color: white;\n  border-width: 4px;\n  margin-left: -4px;\n}\n.w-widget-twitter-count-shim.w--vertical .w-widget-twitter-count-inner {\n  font-size: 18px;\n  line-height: 22px;\n}\n.w-widget-twitter-count-shim.w--vertical.w--large {\n  width: 76px;\n}\n.w-widget-gplus {\n  overflow: hidden;\n}\n.w-background-video {\n  position: relative;\n  overflow: hidden;\n  height: 500px;\n  color: white;\n}\n.w-background-video > video {\n  background-size: cover;\n  background-position: 50% 50%;\n  position: absolute;\n  right: -100%;\n  bottom: -100%;\n  top: -100%;\n  left: -100%;\n  margin: auto;\n  min-width: 100%;\n  min-height: 100%;\n  z-index: -100;\n}\n.w-background-video > video::-webkit-media-controls-start-playback-button {\n  display: none !important;\n  -webkit-appearance: none;\n}\n.w-slider {\n  position: relative;\n  height: 300px;\n  text-align: center;\n  background: #dddddd;\n  clear: both;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n  tap-highlight-color: rgba(0, 0, 0, 0);\n}\n.w-slider-mask {\n  position: relative;\n  display: block;\n  overflow: hidden;\n  z-index: 1;\n  left: 0;\n  right: 0;\n  height: 100%;\n  white-space: nowrap;\n}\n.w-slide {\n  position: relative;\n  display: inline-block;\n  vertical-align: top;\n  width: 100%;\n  height: 100%;\n  white-space: normal;\n  text-align: left;\n}\n.w-slider-nav {\n  position: absolute;\n  z-index: 2;\n  top: auto;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  margin: auto;\n  padding-top: 10px;\n  height: 40px;\n  text-align: center;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n  tap-highlight-color: rgba(0, 0, 0, 0);\n}\n.w-slider-nav.w-round > div {\n  border-radius: 100%;\n}\n.w-slider-nav.w-num > div {\n  width: auto;\n  height: auto;\n  padding: 0.2em 0.5em;\n  font-size: inherit;\n  line-height: inherit;\n}\n.w-slider-nav.w-shadow > div {\n  box-shadow: 0 0 3px rgba(51, 51, 51, 0.4);\n}\n.w-slider-nav-invert {\n  color: #fff;\n}\n.w-slider-nav-invert > div {\n  background-color: rgba(34, 34, 34, 0.4);\n}\n.w-slider-nav-invert > div.w-active {\n  background-color: #222;\n}\n.w-slider-dot {\n  position: relative;\n  display: inline-block;\n  width: 1em;\n  height: 1em;\n  background-color: rgba(255, 255, 255, 0.4);\n  cursor: pointer;\n  margin: 0 3px 0.5em;\n  transition: background-color 100ms, color 100ms;\n}\n.w-slider-dot.w-active {\n  background-color: #fff;\n}\n.w-slider-arrow-left,\n.w-slider-arrow-right {\n  position: absolute;\n  width: 80px;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  margin: auto;\n  cursor: pointer;\n  overflow: hidden;\n  color: white;\n  font-size: 40px;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n  tap-highlight-color: rgba(0, 0, 0, 0);\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n.w-slider-arrow-left [class^=\"w-icon-\"],\n.w-slider-arrow-right [class^=\"w-icon-\"],\n.w-slider-arrow-left [class*=\" w-icon-\"],\n.w-slider-arrow-right [class*=\" w-icon-\"] {\n  position: absolute;\n}\n.w-slider-arrow-left {\n  z-index: 3;\n  right: auto;\n}\n.w-slider-arrow-right {\n  z-index: 4;\n  left: auto;\n}\n.w-icon-slider-left,\n.w-icon-slider-right {\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  margin: auto;\n  width: 1em;\n  height: 1em;\n}\n.w-dropdown {\n  display: inline-block;\n  position: relative;\n  text-align: left;\n  margin-left: auto;\n  margin-right: auto;\n  z-index: 900;\n}\n.w-dropdown-btn,\n.w-dropdown-toggle,\n.w-dropdown-link {\n  position: relative;\n  vertical-align: top;\n  text-decoration: none;\n  color: #222222;\n  padding: 20px;\n  text-align: left;\n  margin-left: auto;\n  margin-right: auto;\n  white-space: nowrap;\n}\n.w-dropdown-toggle {\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  display: inline-block;\n  cursor: pointer;\n  padding-right: 40px;\n}\n.w-icon-dropdown-toggle {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  margin: auto;\n  margin-right: 20px;\n  width: 1em;\n  height: 1em;\n}\n.w-dropdown-list {\n  position: absolute;\n  background: #dddddd;\n  display: none;\n  min-width: 100%;\n}\n.w-dropdown-list.w--open {\n  display: block;\n}\n.w-dropdown-link {\n  padding: 10px 20px;\n  display: block;\n  color: #222222;\n}\n.w-dropdown-link.w--current {\n  color: #0082f3;\n}\n.w-nav[data-collapse=\"all\"] .w-dropdown,\n.w-nav[data-collapse=\"all\"] .w-dropdown-toggle {\n  display: block;\n}\n.w-nav[data-collapse=\"all\"] .w-dropdown-list {\n  position: static;\n}\n@media screen and (max-width: 991px) {\n  .w-nav[data-collapse=\"medium\"] .w-dropdown,\n  .w-nav[data-collapse=\"medium\"] .w-dropdown-toggle {\n    display: block;\n  }\n  .w-nav[data-collapse=\"medium\"] .w-dropdown-list {\n    position: static;\n  }\n}\n@media screen and (max-width: 767px) {\n  .w-nav[data-collapse=\"small\"] .w-dropdown,\n  .w-nav[data-collapse=\"small\"] .w-dropdown-toggle {\n    display: block;\n  }\n  .w-nav[data-collapse=\"small\"] .w-dropdown-list {\n    position: static;\n  }\n  .w-nav-brand {\n    padding-left: 10px;\n  }\n}\n@media screen and (max-width: 479px) {\n  .w-nav[data-collapse=\"tiny\"] .w-dropdown,\n  .w-nav[data-collapse=\"tiny\"] .w-dropdown-toggle {\n    display: block;\n  }\n  .w-nav[data-collapse=\"tiny\"] .w-dropdown-list {\n    position: static;\n  }\n}\n/**\n * ## Note\n * Safari (on both iOS and OS X) does not handle viewport units (vh, vw) well.\n * For example percentage units do not work on descendants of elements that\n * have any dimensions expressed in viewport units. It also doesn’t handle them at\n * all in `calc()`.\n */\n/**\n * Wrapper around all lightbox elements\n *\n * 1. Since the lightbox can receive focus, IE also gives it an outline.\n * 2. Fixes flickering on Chrome when a transition is in progress\n *    underneath the lightbox.\n */\n.w-lightbox-backdrop {\n  color: #000;\n  cursor: auto;\n  font-family: serif;\n  font-size: medium;\n  font-style: normal;\n  font-variant: normal;\n  font-weight: normal;\n  letter-spacing: normal;\n  line-height: normal;\n  list-style: disc;\n  text-align: start;\n  text-indent: 0;\n  text-shadow: none;\n  text-transform: none;\n  visibility: visible;\n  white-space: normal;\n  word-break: normal;\n  word-spacing: normal;\n  word-wrap: normal;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  color: #fff;\n  font-family: \"Helvetica Neue\", Helvetica, Ubuntu, \"Segoe UI\", Verdana, sans-serif;\n  font-size: 17px;\n  line-height: 1.2;\n  font-weight: 300;\n  text-align: center;\n  background: rgba(0, 0, 0, 0.9);\n  z-index: 2000;\n  outline: 0;\n  /* 1 */\n  opacity: 0;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  -webkit-tap-highlight-color: transparent;\n  -webkit-transform: translate(0, 0);\n  /* 2 */\n}\n/**\n * Neat trick to bind the rubberband effect to our canvas instead of the whole\n * document on iOS. It also prevents a bug that causes the document underneath to scroll.\n */\n.w-lightbox-backdrop,\n.w-lightbox-container {\n  height: 100%;\n  overflow: auto;\n  -webkit-overflow-scrolling: touch;\n}\n.w-lightbox-content {\n  position: relative;\n  height: 100vh;\n  overflow: hidden;\n}\n.w-lightbox-view {\n  position: absolute;\n  width: 100vw;\n  height: 100vh;\n  opacity: 0;\n}\n.w-lightbox-view:before {\n  content: \"\";\n  height: 100vh;\n}\n/* .w-lightbox-content */\n.w-lightbox-group,\n.w-lightbox-group .w-lightbox-view,\n.w-lightbox-group .w-lightbox-view:before {\n  height: 86vh;\n}\n.w-lightbox-frame,\n.w-lightbox-view:before {\n  display: inline-block;\n  vertical-align: middle;\n}\n/*\n * 1. Remove default margin set by user-agent on the <figure> element.\n */\n.w-lightbox-figure {\n  position: relative;\n  margin: 0;\n  /* 1 */\n}\n.w-lightbox-group .w-lightbox-figure {\n  cursor: pointer;\n}\n/**\n * IE adds image dimensions as width and height attributes on the IMG tag,\n * but we need both width and height to be set to auto to enable scaling.\n */\n.w-lightbox-img {\n  width: auto;\n  height: auto;\n  max-width: none;\n}\n/**\n * 1. Reset if style is set by user on \"All Images\"\n */\n.w-lightbox-image {\n  display: block;\n  float: none;\n  /* 1 */\n  max-width: 100vw;\n  max-height: 100vh;\n}\n.w-lightbox-group .w-lightbox-image {\n  max-height: 86vh;\n}\n.w-lightbox-caption {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  padding: .5em 1em;\n  background: rgba(0, 0, 0, 0.4);\n  text-align: left;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n}\n.w-lightbox-embed {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\n.w-lightbox-control {\n  position: absolute;\n  top: 0;\n  width: 4em;\n  background-size: 24px;\n  background-repeat: no-repeat;\n  background-position: center;\n  cursor: pointer;\n  -webkit-transition: all .3s;\n  transition: all .3s;\n}\n.w-lightbox-left {\n  display: none;\n  bottom: 0;\n  left: 0;\n  /* <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"-20 0 24 40\" width=\"24\" height=\"40\"><g transform=\"rotate(45)\"><path d=\"m0 0h5v23h23v5h-28z\" opacity=\".4\"/><path d=\"m1 1h3v23h23v3h-26z\" fill=\"#fff\"/></g></svg> */\n  background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0yMCAwIDI0IDQwIiB3aWR0aD0iMjQiIGhlaWdodD0iNDAiPjxnIHRyYW5zZm9ybT0icm90YXRlKDQ1KSI+PHBhdGggZD0ibTAgMGg1djIzaDIzdjVoLTI4eiIgb3BhY2l0eT0iLjQiLz48cGF0aCBkPSJtMSAxaDN2MjNoMjN2M2gtMjZ6IiBmaWxsPSIjZmZmIi8+PC9nPjwvc3ZnPg==\");\n}\n.w-lightbox-right {\n  display: none;\n  right: 0;\n  bottom: 0;\n  /* <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"-4 0 24 40\" width=\"24\" height=\"40\"><g transform=\"rotate(45)\"><path d=\"m0-0h28v28h-5v-23h-23z\" opacity=\".4\"/><path d=\"m1 1h26v26h-3v-23h-23z\" fill=\"#fff\"/></g></svg> */\n  background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii00IDAgMjQgNDAiIHdpZHRoPSIyNCIgaGVpZ2h0PSI0MCI+PGcgdHJhbnNmb3JtPSJyb3RhdGUoNDUpIj48cGF0aCBkPSJtMC0waDI4djI4aC01di0yM2gtMjN6IiBvcGFjaXR5PSIuNCIvPjxwYXRoIGQ9Im0xIDFoMjZ2MjZoLTN2LTIzaC0yM3oiIGZpbGw9IiNmZmYiLz48L2c+PC9zdmc+\");\n}\n/*\n * Without specifying the with and height inside the SVG, all versions of IE render the icon too small.\n * The bug does not seem to manifest itself if the elements are tall enough such as the above arrows.\n * (http://stackoverflow.com/questions/16092114/background-size-differs-in-internet-explorer)\n */\n.w-lightbox-close {\n  right: 0;\n  height: 2.6em;\n  /* <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"-4 0 18 17\" width=\"18\" height=\"17\"><g transform=\"rotate(45)\"><path d=\"m0 0h7v-7h5v7h7v5h-7v7h-5v-7h-7z\" opacity=\".4\"/><path d=\"m1 1h7v-7h3v7h7v3h-7v7h-3v-7h-7z\" fill=\"#fff\"/></g></svg> */\n  background-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii00IDAgMTggMTciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxNyI+PGcgdHJhbnNmb3JtPSJyb3RhdGUoNDUpIj48cGF0aCBkPSJtMCAwaDd2LTdoNXY3aDd2NWgtN3Y3aC01di03aC03eiIgb3BhY2l0eT0iLjQiLz48cGF0aCBkPSJtMSAxaDd2LTdoM3Y3aDd2M2gtN3Y3aC0zdi03aC03eiIgZmlsbD0iI2ZmZiIvPjwvZz48L3N2Zz4=\");\n  background-size: 18px;\n}\n/**\n * 1. All IE versions add extra space at the bottom without this.\n */\n.w-lightbox-strip {\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  padding: 0 1vh;\n  line-height: 0;\n  /* 1 */\n  white-space: nowrap;\n  overflow-x: auto;\n  overflow-y: hidden;\n}\n/*\n * 1. We use content-box to avoid having to do `width: calc(10vh + 2vw)`\n *    which doesn’t work in Safari anyway.\n * 2. Chrome renders images pixelated when switching to GPU. Making sure\n *    the parent is also rendered on the GPU (by setting translate3d for\n *    example) fixes this behavior.\n */\n.w-lightbox-item {\n  display: inline-block;\n  width: 10vh;\n  padding: 2vh 1vh;\n  box-sizing: content-box;\n  /* 1 */\n  cursor: pointer;\n  -webkit-transform: translate3d(0, 0, 0);\n  /* 2 */\n}\n.w-lightbox-active {\n  opacity: .3;\n}\n.w-lightbox-thumbnail {\n  position: relative;\n  height: 10vh;\n  background: #222;\n  overflow: hidden;\n}\n.w-lightbox-thumbnail-image {\n  position: absolute;\n  top: 0;\n  left: 0;\n}\n.w-lightbox-thumbnail .w-lightbox-tall {\n  top: 50%;\n  width: 100%;\n  -webkit-transform: translate(0, -50%);\n  -ms-transform: translate(0, -50%);\n  transform: translate(0, -50%);\n}\n.w-lightbox-thumbnail .w-lightbox-wide {\n  left: 50%;\n  height: 100%;\n  -webkit-transform: translate(-50%, 0);\n  -ms-transform: translate(-50%, 0);\n  transform: translate(-50%, 0);\n}\n/*\n * Spinner\n *\n * Absolute pixel values are used to avoid rounding errors that would cause\n * the white spinning element to be misaligned with the track.\n */\n.w-lightbox-spinner {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  box-sizing: border-box;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  margin-left: -20px;\n  border: 5px solid rgba(0, 0, 0, 0.4);\n  border-radius: 50%;\n  -webkit-animation: spin .8s infinite linear;\n  animation: spin .8s infinite linear;\n}\n.w-lightbox-spinner:after {\n  content: \"\";\n  position: absolute;\n  top: -4px;\n  right: -4px;\n  bottom: -4px;\n  left: -4px;\n  border: 3px solid transparent;\n  border-bottom-color: #fff;\n  border-radius: 50%;\n}\n/*\n * Utility classes\n */\n.w-lightbox-hide {\n  display: none;\n}\n.w-lightbox-noscroll {\n  overflow: hidden;\n}\n@media (min-width: 768px) {\n  .w-lightbox-content {\n    height: 96vh;\n    margin-top: 2vh;\n  }\n  .w-lightbox-view,\n  .w-lightbox-view:before {\n    height: 96vh;\n  }\n  /* .w-lightbox-content */\n  .w-lightbox-group,\n  .w-lightbox-group .w-lightbox-view,\n  .w-lightbox-group .w-lightbox-view:before {\n    height: 84vh;\n  }\n  .w-lightbox-image {\n    max-width: 96vw;\n    max-height: 96vh;\n  }\n  .w-lightbox-group .w-lightbox-image {\n    max-width: 82.3vw;\n    max-height: 84vh;\n  }\n  .w-lightbox-left,\n  .w-lightbox-right {\n    display: block;\n    opacity: .5;\n  }\n  .w-lightbox-close {\n    opacity: .8;\n  }\n  .w-lightbox-control:hover {\n    opacity: 1;\n  }\n}\n.w-lightbox-inactive,\n.w-lightbox-inactive:hover {\n  opacity: 0;\n}\n.w-richtext:before,\n.w-richtext:after {\n  content: \" \";\n  display: table;\n}\n.w-richtext:after {\n  clear: both;\n}\n.w-richtext[contenteditable=\"true\"]:before,\n.w-richtext[contenteditable=\"true\"]:after {\n  white-space: initial;\n}\n.w-richtext ol,\n.w-richtext ul {\n  overflow: hidden;\n}\n.w-richtext .w-richtext-figure-selected.w-richtext-figure-type-video div:before,\n.w-richtext .w-richtext-figure-selected[data-rt-type=\"video\"] div:before {\n  outline: 2px solid #2895f7;\n}\n.w-richtext .w-richtext-figure-selected.w-richtext-figure-type-image div,\n.w-richtext .w-richtext-figure-selected[data-rt-type=\"image\"] div {\n  outline: 2px solid #2895f7;\n}\n.w-richtext figure.w-richtext-figure-type-video > div:before,\n.w-richtext figure[data-rt-type=\"video\"] > div:before {\n  content: '';\n  position: absolute;\n  display: none;\n  left: 0;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  z-index: 1;\n}\n.w-richtext figure {\n  position: relative;\n  max-width: 60%;\n}\n.w-richtext figure > div:before {\n  cursor: default!important;\n}\n.w-richtext figure img {\n  width: 100%;\n}\n.w-richtext figure figcaption.w-richtext-figcaption-placeholder {\n  opacity: 0.6;\n}\n.w-richtext figure div {\n  /* fix incorrectly sized selection border in the data manager */\n  font-size: 0px;\n  color: transparent;\n}\n.w-richtext figure.w-richtext-figure-type-image,\n.w-richtext figure[data-rt-type=\"image\"] {\n  display: table;\n}\n.w-richtext figure.w-richtext-figure-type-image > div,\n.w-richtext figure[data-rt-type=\"image\"] > div {\n  display: inline-block;\n}\n.w-richtext figure.w-richtext-figure-type-image > figcaption,\n.w-richtext figure[data-rt-type=\"image\"] > figcaption {\n  display: table-caption;\n  caption-side: bottom;\n}\n.w-richtext figure.w-richtext-figure-type-video,\n.w-richtext figure[data-rt-type=\"video\"] {\n  width: 60%;\n  height: 0;\n}\n.w-richtext figure.w-richtext-figure-type-video iframe,\n.w-richtext figure[data-rt-type=\"video\"] iframe {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\n.w-richtext figure.w-richtext-figure-type-video > div,\n.w-richtext figure[data-rt-type=\"video\"] > div {\n  width: 100%;\n}\n.w-richtext figure.w-richtext-align-center {\n  margin-right: auto;\n  margin-left: auto;\n  clear: both;\n}\n.w-richtext figure.w-richtext-align-center.w-richtext-figure-type-image > div,\n.w-richtext figure.w-richtext-align-center[data-rt-type=\"image\"] > div {\n  max-width: 100%;\n}\n.w-richtext figure.w-richtext-align-normal {\n  clear: both;\n}\n.w-richtext figure.w-richtext-align-fullwidth {\n  width: 100%;\n  max-width: 100%;\n  text-align: center;\n  clear: both;\n  display: block;\n  margin-right: auto;\n  margin-left: auto;\n}\n.w-richtext figure.w-richtext-align-fullwidth > div {\n  display: inline-block;\n  /* padding-bottom is used for aspect ratios in video figures\n      we want the div to inherit that so hover/selection borders in the designer-canvas\n      fit right*/\n  padding-bottom: inherit;\n}\n.w-richtext figure.w-richtext-align-fullwidth > figcaption {\n  display: block;\n}\n.w-richtext figure.w-richtext-align-floatleft {\n  float: left;\n  margin-right: 15px;\n  clear: none;\n}\n.w-richtext figure.w-richtext-align-floatright {\n  float: right;\n  margin-left: 15px;\n  clear: none;\n}\n.w-nav {\n  position: relative;\n  background: #dddddd;\n  z-index: 1000;\n}\n.w-nav:before,\n.w-nav:after {\n  content: \" \";\n  display: table;\n}\n.w-nav:after {\n  clear: both;\n}\n.w-nav-brand {\n  position: relative;\n  float: left;\n  text-decoration: none;\n  color: #333333;\n}\n.w-nav-link {\n  position: relative;\n  display: inline-block;\n  vertical-align: top;\n  text-decoration: none;\n  color: #222222;\n  padding: 20px;\n  text-align: left;\n  margin-left: auto;\n  margin-right: auto;\n}\n.w-nav-link.w--current {\n  color: #0082f3;\n}\n.w-nav-menu {\n  position: relative;\n  float: right;\n}\n.w--nav-menu-open {\n  display: block !important;\n  position: absolute;\n  top: 100%;\n  left: 0;\n  right: 0;\n  background: #C8C8C8;\n  text-align: center;\n  overflow: visible;\n  min-width: 200px;\n}\n.w--nav-link-open {\n  display: block;\n  position: relative;\n}\n.w-nav-overlay {\n  position: absolute;\n  overflow: hidden;\n  display: none;\n  top: 100%;\n  left: 0;\n  right: 0;\n  width: 100%;\n}\n.w-nav-overlay .w--nav-menu-open {\n  top: 0;\n}\n.w-nav[data-animation=\"over-left\"] .w-nav-overlay {\n  width: auto;\n}\n.w-nav[data-animation=\"over-left\"] .w-nav-overlay,\n.w-nav[data-animation=\"over-left\"] .w--nav-menu-open {\n  right: auto;\n  z-index: 1;\n  top: 0;\n}\n.w-nav[data-animation=\"over-right\"] .w-nav-overlay {\n  width: auto;\n}\n.w-nav[data-animation=\"over-right\"] .w-nav-overlay,\n.w-nav[data-animation=\"over-right\"] .w--nav-menu-open {\n  left: auto;\n  z-index: 1;\n  top: 0;\n}\n.w-nav-button {\n  position: relative;\n  float: right;\n  padding: 18px;\n  font-size: 24px;\n  display: none;\n  cursor: pointer;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n  tap-highlight-color: rgba(0, 0, 0, 0);\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n.w-nav-button.w--open {\n  background-color: #C8C8C8;\n  color: white;\n}\n.w-nav[data-collapse=\"all\"] .w-nav-menu {\n  display: none;\n}\n.w-nav[data-collapse=\"all\"] .w-nav-button {\n  display: block;\n}\n@media screen and (max-width: 991px) {\n  .w-nav[data-collapse=\"medium\"] .w-nav-menu {\n    display: none;\n  }\n  .w-nav[data-collapse=\"medium\"] .w-nav-button {\n    display: block;\n  }\n}\n@media screen and (max-width: 767px) {\n  .w-nav[data-collapse=\"small\"] .w-nav-menu {\n    display: none;\n  }\n  .w-nav[data-collapse=\"small\"] .w-nav-button {\n    display: block;\n  }\n  .w-nav-brand {\n    padding-left: 10px;\n  }\n}\n@media screen and (max-width: 479px) {\n  .w-nav[data-collapse=\"tiny\"] .w-nav-menu {\n    display: none;\n  }\n  .w-nav[data-collapse=\"tiny\"] .w-nav-button {\n    display: block;\n  }\n}\n.w-tabs {\n  position: relative;\n}\n.w-tabs:before,\n.w-tabs:after {\n  content: \" \";\n  display: table;\n}\n.w-tabs:after {\n  clear: both;\n}\n.w-tab-menu {\n  position: relative;\n}\n.w-tab-link {\n  position: relative;\n  display: inline-block;\n  vertical-align: top;\n  text-decoration: none;\n  padding: 9px 30px;\n  text-align: left;\n  cursor: pointer;\n  color: #222222;\n  background-color: #dddddd;\n}\n.w-tab-link.w--current {\n  background-color: #C8C8C8;\n}\n.w-tab-content {\n  position: relative;\n  display: block;\n  overflow: hidden;\n}\n.w-tab-pane {\n  position: relative;\n  display: none;\n}\n.w--tab-active {\n  display: block;\n}\n@media screen and (max-width: 479px) {\n  .w-tab-link {\n    display: block;\n  }\n}\n.w-ix-emptyfix:after {\n  content: \"\";\n}\n@keyframes spin {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n.w-dyn-empty {\n  padding: 10px;\n  background-color: #dddddd;\n}\n.w-dyn-bind-empty {\n  display: none !important;\n}\n.w-condition-invisible {\n  display: none !important;\n}\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<!--  Last Published: Thu Aug 09 2018 08:47:02 GMT+0000 (UTC)  -->\n<html data-wf-page=\"574f0289c3c4633629a7737c\" data-wf-site=\"574f0289c3c4633629a7737b\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>States of the artboard - Sketch Plugin</title>\n  <meta content=\"Create different states and switch between them easily. Just like layer comps for Sketch.\" name=\"description\">\n  <meta content=\"States of the artboard - Sketch Plugin\" property=\"og:title\">\n  <meta content=\"Create different states and switch between them easily. Just like layer comps for Sketch.\" property=\"og:description\">\n  <meta content=\"summary\" name=\"twitter:card\">\n  <meta content=\"width=device-width, initial-scale=1\" name=\"viewport\">\n  <link href=\"css/normalize.css\" rel=\"stylesheet\" type=\"text/css\">\n  <link href=\"css/webflow.css\" rel=\"stylesheet\" type=\"text/css\">\n  <link href=\"css/states.webflow.css\" rel=\"stylesheet\" type=\"text/css\">\n  <script src=\"https://ajax.googleapis.com/ajax/libs/webfont/1.4.7/webfont.js\" type=\"text/javascript\"></script>\n  <script type=\"text/javascript\">\n      WebFont.load({\n        google: {\n          families: [\"Playfair Display:regular,italic,700,700italic,900,900italic:latin-ext,latin,cyrillic\", \"Work Sans:100,200,300,regular,500,600,700,800,900:latin-ext,latin\"]\n        }\n      });\n    </script>\n  <!-- [if lt IE 9]><script src=\"https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js\" type=\"text/javascript\"></script><![endif] -->\n  <script type=\"text/javascript\">\n      ! function(o, c) {\n        var n = c.documentElement,\n          t = \" w-mod-\";\n        n.className += t + \"js\", (\"ontouchstart\" in o || o.DocumentTouch && c instanceof DocumentTouch) && (n.className += t + \"touch\")\n      }(window, document);\n    </script>\n  <link href=\"images/favicon.png\" rel=\"shortcut icon\" type=\"image/x-icon\">\n  <link href=\"images/favbig.png\" rel=\"apple-touch-icon\">\n  <script type=\"text/javascript\">\n      var _gaq = _gaq || [];\n      _gaq.push(['_setAccount', 'UA-79358404-1'], ['_trackPageview']);\n      (function() {\n        var ga = document.createElement('script');\n        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n        var s = document.getElementsByTagName('script')[0];\n        s.parentNode.insertBefore(ga, s);\n      })();\n    </script>\n  <style>\n      body {\n        font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n        overflow-x: hidden;\n        -webkit-font-smoothing: antialiased;\n      }\n    </style>\n</head>\n<body><img src=\"images/share.png\" srcset=\"images/share-p-500x262.png 500w, images/share-p-800x418.png 800w, images/share-p-1080x565.png 1080w, images/share.png 1200w\" sizes=\"100vw\" class=\"w-hidden-main w-hidden-medium w-hidden-small w-hidden-tiny\">\n  <div class=\"social\"><a href=\"https://twitter.com/intent/tweet?text=States of the artboard - Sketch Plugin. Just like layer comps for Sketch. http://states.design\" data-via=\"@ishkash_8\" data-url=\"http://states.design\" class=\"icon w-inline-block\"><img src=\"images/t.png\" width=\"22\" class=\"shadow\"></a>\n    <div class=\"w-embed\"><a class=\"icon-facebook\" rel=\"nofollow\" href=\"http://www.facebook.com/\" onclick=\"popUp=window.open(\n        'http://www.facebook.com/sharer.php?u=http://states.design',\n        'popupwindow',\n        'scrollbars=yes,width=800,height=400');\n    popUp.focus();\n    return false\">\n<img src=\"images/f.png\" style=\"width:10px;\">\n</a></div>\n    <div class=\"w-hidden-main w-hidden-medium w-hidden-small w-hidden-tiny w-embed w-script\">\n      <script>\n          window.twttr = (function(d, s, id) {\n            var js, fjs = d.getElementsByTagName(s)[0],\n              t = window.twttr || {};\n            if (d.getElementById(id)) return t;\n            js = d.createElement(s);\n            js.id = id;\n            js.src = \"https://platform.twitter.com/widgets.js\";\n            fjs.parentNode.insertBefore(js, fjs);\n            t._e = [];\n            t.ready = function(f) {\n              t._e.push(f);\n            };\n            return t;\n          }(document, \"script\", \"twitter-wjs\"));\n        </script>\n    </div>\n  </div>\n  <div class=\"section black bg\">\n    <div class=\"_25 w-container\">\n      <h1 class=\"bold\">States<br>of the\n        <br>artboard</h1>\n      <a href=\"#Demo\" class=\"w-inline-block\">\n        <h2 class=\"white bold\">See how it works</h2>\n      </a>\n    </div>\n    <div class=\"_50 w-container\"></div>\n    <div class=\"_25 w-container\">\n      <div><img src=\"images/blk.png\" class=\"icon\"><img src=\"images/sketch.png\" class=\"icon\"></div>\n      <h2 class=\"white\">Sketch Plugin</h2>\n      <h2 class=\"white space\">Create different states and switch between them easily. Just like layer comps for Sketch.</h2>\n      <div class=\"none w-embed\"><a class=\"button white\" onclick=\"ga('send', 'event', 'File', 'Download', 'Click');\" href=\"https://github.com/edenvidal/States/releases/download/v0.99/States.sketchplugin.v0.99.zip\">Download</a></div>\n    </div>\n  </div>\n  <div id=\"Demo\" class=\"section artboard\">\n    <div class=\"_25 long w-container\">\n      <div><img src=\"images/position.png\" class=\"icon\"><img src=\"images/visible.png\" class=\"icon\">\n        <p class=\"_75\">Define different positions and toggle visibility of your layers.</p>\n      </div>\n      <div><img src=\"images/add.png\" class=\"icon\"><img src=\"images/update.png\" class=\"icon\">\n        <p class=\"_75\">Create new states and update changes. Create pages with new artboards from your states.</p>\n      </div>\n    </div>\n    <div class=\"_33 w-container\"></div>\n  </div>\n  <div class=\"section black bg2\">\n    <div class=\"_25 w-container\"><img src=\"images/logo.png\">\n      <h2 class=\"white w-clearfix\">Created with love for the design community and the good people of the earth.<br><br><a target=\"_blank\" href=\"https://medium.com/@edenvidal/states-of-the-artboard-sketch-plugin-951516600c50#.j21tkp82g\" class=\"white bold\">Read the post on Medium</a></h2><a target=\"_blank\" href=\"https://github.com/edenvidal/States\" class=\"icon w-inline-block\"><img src=\"images/git.png\" width=\"22\" class=\"shadow\"></a></div>\n    <div class=\"_25 bottom w-container\"></div>\n    <div class=\"_25 bottom w-container\"></div>\n    <div class=\"_25 w-container\">\n      <h2 class=\"white\">By <a href=\"http://edenvidal.com/\" target=\"_blank\">Eden Vidal</a><a href=\"http://internals.exposed/\" target=\"_blank\"></a></h2>\n      <p class=\"white w-clearfix\">Please let me know if this works for you and how – any feedback, ideas, or bugs.</p>\n    </div>\n  </div>\n  <script src=\"https://code.jquery.com/jquery-3.3.1.min.js\" type=\"text/javascript\" integrity=\"sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=\" crossorigin=\"anonymous\"></script>\n  <script src=\"js/webflow.js\" type=\"text/javascript\"></script>\n  <!-- [if lte IE 9]><script src=\"https://cdnjs.cloudflare.com/ajax/libs/placeholders/3.0.2/placeholders.min.js\"></script><![endif] -->\n  <!--  Google Analytics  -->\n  <script>\n      (function(i, s, o, g, r, a, m) {\n        i['GoogleAnalyticsObject'] = r;\n        i[r] = i[r] || function() {\n          (i[r].q = i[r].q || []).push(arguments)\n        }, i[r].l = 1 * new Date();\n        a = s.createElement(o),\n          m = s.getElementsByTagName(o)[0];\n        a.async = 1;\n        a.src = g;\n        m.parentNode.insertBefore(a, m)\n      })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');\n      ga('create', 'UA-79358404-1', 'auto');\n      ga('send', 'pageview');\n    </script>\n  <!--  End Google Analytics  -->\n</body>\n</html>"
  },
  {
    "path": "js/webflow.js",
    "content": "/*!\n * Webflow: Front-end site library\n * @license MIT\n * Inline scripts may access the api using an async handler:\n *   var Webflow = Webflow || [];\n *   Webflow.push(readyFunction);\n */!function(t){var e={};function n(i){if(e[i])return e[i].exports;var r=e[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:i})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,\"a\",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p=\"\",n(n.s=2)}([function(t,e,n){var i={},r={},o=[],s=window.Webflow||[],a=window.jQuery,u=a(window),c=a(document),l=a.isFunction,f=i._=n(4),h=n(1)&&a.tram,d=!1,p=!1;function v(t){i.env()&&(l(t.design)&&u.on(\"__wf_design\",t.design),l(t.preview)&&u.on(\"__wf_preview\",t.preview)),l(t.destroy)&&u.on(\"__wf_destroy\",t.destroy),t.ready&&l(t.ready)&&function(t){if(d)return void t.ready();if(f.contains(o,t.ready))return;o.push(t.ready)}(t)}function m(t){l(t.design)&&u.off(\"__wf_design\",t.design),l(t.preview)&&u.off(\"__wf_preview\",t.preview),l(t.destroy)&&u.off(\"__wf_destroy\",t.destroy),t.ready&&l(t.ready)&&function(t){o=f.filter(o,function(e){return e!==t.ready})}(t)}h.config.hideBackface=!1,h.config.keepInherited=!0,i.define=function(t,e,n){r[t]&&m(r[t]);var i=r[t]=e(a,f,n)||{};return v(i),i},i.require=function(t){return r[t]},i.push=function(t){d?l(t)&&t():s.push(t)},i.env=function(t){var e=window.__wf_design,n=void 0!==e;return t?\"design\"===t?n&&e:\"preview\"===t?n&&!e:\"slug\"===t?n&&window.__wf_slug:\"editor\"===t?window.WebflowEditor:\"test\"===t?window.__wf_test:\"frame\"===t?window!==window.top:void 0:n};var w,g=navigator.userAgent.toLowerCase(),b=i.env.touch=\"ontouchstart\"in window||window.DocumentTouch&&document instanceof window.DocumentTouch,y=i.env.chrome=/chrome/.test(g)&&/Google/.test(navigator.vendor)&&parseInt(g.match(/chrome\\/(\\d+)\\./)[1],10),x=i.env.ios=/(ipod|iphone|ipad)/.test(g);i.env.safari=/safari/.test(g)&&!y&&!x,b&&c.on(\"touchstart mousedown\",function(t){w=t.target}),i.validClick=b?function(t){return t===w||a.contains(t,w)}:function(){return!0};var _,k=\"resize.webflow orientationchange.webflow load.webflow\";function z(t,e){var n=[],i={};return i.up=f.throttle(function(t){f.each(n,function(e){e(t)})}),t&&e&&t.on(e,i.up),i.on=function(t){\"function\"==typeof t&&(f.contains(n,t)||n.push(t))},i.off=function(t){n=arguments.length?f.filter(n,function(e){return e!==t}):[]},i}function T(t){l(t)&&t()}function E(){_&&(_.reject(),u.off(\"load\",_.resolve)),_=new a.Deferred,u.on(\"load\",_.resolve)}i.resize=z(u,k),i.scroll=z(u,\"scroll.webflow resize.webflow orientationchange.webflow load.webflow\"),i.redraw=z(),i.location=function(t){window.location=t},i.env()&&(i.location=function(){}),i.ready=function(){d=!0,p?(p=!1,f.each(r,v)):f.each(o,T),f.each(s,T),i.resize.up()},i.load=function(t){_.then(t)},i.destroy=function(t){t=t||{},p=!0,u.triggerHandler(\"__wf_destroy\"),null!=t.domready&&(d=t.domready),f.each(r,m),i.resize.off(),i.scroll.off(),i.redraw.off(),o=[],s=[],\"pending\"===_.state()&&E()},a(i.ready),E(),t.exports=window.Webflow=i},function(t,e){var n=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&\"function\"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t};window.tram=function(t){function e(t,e){return(new L.Bare).init(t,e)}function i(t){return t.replace(/[A-Z]/g,function(t){return\"-\"+t.toLowerCase()})}function r(t){var e=parseInt(t.slice(1),16);return[e>>16&255,e>>8&255,255&e]}function o(t,e,n){return\"#\"+(1<<24|t<<16|e<<8|n).toString(16).slice(1)}function s(){}function a(t,e,n){c(\"Units do not match [\"+t+\"]: \"+e+\", \"+n)}function u(t,e,n){if(void 0!==e&&(n=e),void 0===t)return n;var i=n;return J.test(t)||!V.test(t)?i=parseInt(t,10):V.test(t)&&(i=1e3*parseFloat(t)),0>i&&(i=0),i==i?i:n}function c(t){X.debug&&window&&window.console.warn(t)}var l=function(t,e,i){function r(t){return\"object\"==(void 0===t?\"undefined\":n(t))}function o(t){return\"function\"==typeof t}function s(){}return function n(a,u){function c(){var t=new l;return o(t.init)&&t.init.apply(t,arguments),t}function l(){}u===i&&(u=a,a=Object),c.Bare=l;var f,h=s[t]=a[t],d=l[t]=c[t]=new s;return d.constructor=c,c.mixin=function(e){return l[t]=c[t]=n(c,e)[t],c},c.open=function(t){if(f={},o(t)?f=t.call(c,d,h,c,a):r(t)&&(f=t),r(f))for(var n in f)e.call(f,n)&&(d[n]=f[n]);return o(d.init)||(d.init=a),c},c.open(u)}}(\"prototype\",{}.hasOwnProperty),f={ease:[\"ease\",function(t,e,n,i){var r=(t/=i)*t,o=r*t;return e+n*(-2.75*o*r+11*r*r+-15.5*o+8*r+.25*t)}],\"ease-in\":[\"ease-in\",function(t,e,n,i){var r=(t/=i)*t,o=r*t;return e+n*(-1*o*r+3*r*r+-3*o+2*r)}],\"ease-out\":[\"ease-out\",function(t,e,n,i){var r=(t/=i)*t,o=r*t;return e+n*(.3*o*r+-1.6*r*r+2.2*o+-1.8*r+1.9*t)}],\"ease-in-out\":[\"ease-in-out\",function(t,e,n,i){var r=(t/=i)*t,o=r*t;return e+n*(2*o*r+-5*r*r+2*o+2*r)}],linear:[\"linear\",function(t,e,n,i){return n*t/i+e}],\"ease-in-quad\":[\"cubic-bezier(0.550, 0.085, 0.680, 0.530)\",function(t,e,n,i){return n*(t/=i)*t+e}],\"ease-out-quad\":[\"cubic-bezier(0.250, 0.460, 0.450, 0.940)\",function(t,e,n,i){return-n*(t/=i)*(t-2)+e}],\"ease-in-out-quad\":[\"cubic-bezier(0.455, 0.030, 0.515, 0.955)\",function(t,e,n,i){return(t/=i/2)<1?n/2*t*t+e:-n/2*(--t*(t-2)-1)+e}],\"ease-in-cubic\":[\"cubic-bezier(0.550, 0.055, 0.675, 0.190)\",function(t,e,n,i){return n*(t/=i)*t*t+e}],\"ease-out-cubic\":[\"cubic-bezier(0.215, 0.610, 0.355, 1)\",function(t,e,n,i){return n*((t=t/i-1)*t*t+1)+e}],\"ease-in-out-cubic\":[\"cubic-bezier(0.645, 0.045, 0.355, 1)\",function(t,e,n,i){return(t/=i/2)<1?n/2*t*t*t+e:n/2*((t-=2)*t*t+2)+e}],\"ease-in-quart\":[\"cubic-bezier(0.895, 0.030, 0.685, 0.220)\",function(t,e,n,i){return n*(t/=i)*t*t*t+e}],\"ease-out-quart\":[\"cubic-bezier(0.165, 0.840, 0.440, 1)\",function(t,e,n,i){return-n*((t=t/i-1)*t*t*t-1)+e}],\"ease-in-out-quart\":[\"cubic-bezier(0.770, 0, 0.175, 1)\",function(t,e,n,i){return(t/=i/2)<1?n/2*t*t*t*t+e:-n/2*((t-=2)*t*t*t-2)+e}],\"ease-in-quint\":[\"cubic-bezier(0.755, 0.050, 0.855, 0.060)\",function(t,e,n,i){return n*(t/=i)*t*t*t*t+e}],\"ease-out-quint\":[\"cubic-bezier(0.230, 1, 0.320, 1)\",function(t,e,n,i){return n*((t=t/i-1)*t*t*t*t+1)+e}],\"ease-in-out-quint\":[\"cubic-bezier(0.860, 0, 0.070, 1)\",function(t,e,n,i){return(t/=i/2)<1?n/2*t*t*t*t*t+e:n/2*((t-=2)*t*t*t*t+2)+e}],\"ease-in-sine\":[\"cubic-bezier(0.470, 0, 0.745, 0.715)\",function(t,e,n,i){return-n*Math.cos(t/i*(Math.PI/2))+n+e}],\"ease-out-sine\":[\"cubic-bezier(0.390, 0.575, 0.565, 1)\",function(t,e,n,i){return n*Math.sin(t/i*(Math.PI/2))+e}],\"ease-in-out-sine\":[\"cubic-bezier(0.445, 0.050, 0.550, 0.950)\",function(t,e,n,i){return-n/2*(Math.cos(Math.PI*t/i)-1)+e}],\"ease-in-expo\":[\"cubic-bezier(0.950, 0.050, 0.795, 0.035)\",function(t,e,n,i){return 0===t?e:n*Math.pow(2,10*(t/i-1))+e}],\"ease-out-expo\":[\"cubic-bezier(0.190, 1, 0.220, 1)\",function(t,e,n,i){return t===i?e+n:n*(1-Math.pow(2,-10*t/i))+e}],\"ease-in-out-expo\":[\"cubic-bezier(1, 0, 0, 1)\",function(t,e,n,i){return 0===t?e:t===i?e+n:(t/=i/2)<1?n/2*Math.pow(2,10*(t-1))+e:n/2*(2-Math.pow(2,-10*--t))+e}],\"ease-in-circ\":[\"cubic-bezier(0.600, 0.040, 0.980, 0.335)\",function(t,e,n,i){return-n*(Math.sqrt(1-(t/=i)*t)-1)+e}],\"ease-out-circ\":[\"cubic-bezier(0.075, 0.820, 0.165, 1)\",function(t,e,n,i){return n*Math.sqrt(1-(t=t/i-1)*t)+e}],\"ease-in-out-circ\":[\"cubic-bezier(0.785, 0.135, 0.150, 0.860)\",function(t,e,n,i){return(t/=i/2)<1?-n/2*(Math.sqrt(1-t*t)-1)+e:n/2*(Math.sqrt(1-(t-=2)*t)+1)+e}],\"ease-in-back\":[\"cubic-bezier(0.600, -0.280, 0.735, 0.045)\",function(t,e,n,i,r){return void 0===r&&(r=1.70158),n*(t/=i)*t*((r+1)*t-r)+e}],\"ease-out-back\":[\"cubic-bezier(0.175, 0.885, 0.320, 1.275)\",function(t,e,n,i,r){return void 0===r&&(r=1.70158),n*((t=t/i-1)*t*((r+1)*t+r)+1)+e}],\"ease-in-out-back\":[\"cubic-bezier(0.680, -0.550, 0.265, 1.550)\",function(t,e,n,i,r){return void 0===r&&(r=1.70158),(t/=i/2)<1?n/2*t*t*((1+(r*=1.525))*t-r)+e:n/2*((t-=2)*t*((1+(r*=1.525))*t+r)+2)+e}]},h={\"ease-in-back\":\"cubic-bezier(0.600, 0, 0.735, 0.045)\",\"ease-out-back\":\"cubic-bezier(0.175, 0.885, 0.320, 1)\",\"ease-in-out-back\":\"cubic-bezier(0.680, 0, 0.265, 1)\"},d=document,p=window,v=\"bkwld-tram\",m=/[\\-\\.0-9]/g,w=/[A-Z]/,g=\"number\",b=/^(rgb|#)/,y=/(em|cm|mm|in|pt|pc|px)$/,x=/(em|cm|mm|in|pt|pc|px|%)$/,_=/(deg|rad|turn)$/,k=\"unitless\",z=/(all|none) 0s ease 0s/,T=/^(width|height)$/,E=\" \",q=d.createElement(\"a\"),O=[\"Webkit\",\"Moz\",\"O\",\"ms\"],A=[\"-webkit-\",\"-moz-\",\"-o-\",\"-ms-\"],S=function(t){if(t in q.style)return{dom:t,css:t};var e,n,i=\"\",r=t.split(\"-\");for(e=0;e<r.length;e++)i+=r[e].charAt(0).toUpperCase()+r[e].slice(1);for(e=0;e<O.length;e++)if((n=O[e]+i)in q.style)return{dom:n,css:A[e]+t}},$=e.support={bind:Function.prototype.bind,transform:S(\"transform\"),transition:S(\"transition\"),backface:S(\"backface-visibility\"),timing:S(\"transition-timing-function\")};if($.transition){var j=$.timing.dom;if(q.style[j]=f[\"ease-in-back\"][0],!q.style[j])for(var M in h)f[M][0]=h[M]}var B=e.frame=function(){var t=p.requestAnimationFrame||p.webkitRequestAnimationFrame||p.mozRequestAnimationFrame||p.oRequestAnimationFrame||p.msRequestAnimationFrame;return t&&$.bind?t.bind(p):function(t){p.setTimeout(t,16)}}(),R=e.now=function(){var t=p.performance,e=t&&(t.now||t.webkitNow||t.msNow||t.mozNow);return e&&$.bind?e.bind(t):Date.now||function(){return+new Date}}(),F=l(function(e){function r(t,e){var n=function(t){for(var e=-1,n=t?t.length:0,i=[];++e<n;){var r=t[e];r&&i.push(r)}return i}((\"\"+t).split(E)),i=n[0];e=e||{};var r=W[i];if(!r)return c(\"Unsupported property: \"+i);if(!e.weak||!this.props[i]){var o=r[0],s=this.props[i];return s||(s=this.props[i]=new o.Bare),s.init(this.$el,n,r,e),s}}function o(t,e,i){if(t){var o=void 0===t?\"undefined\":n(t);if(e||(this.timer&&this.timer.destroy(),this.queue=[],this.active=!1),\"number\"==o&&e)return this.timer=new N({duration:t,context:this,complete:s}),void(this.active=!0);if(\"string\"==o&&e){switch(t){case\"hide\":l.call(this);break;case\"stop\":a.call(this);break;case\"redraw\":f.call(this);break;default:r.call(this,t,i&&i[1])}return s.call(this)}if(\"function\"==o)return void t.call(this,this);if(\"object\"==o){var c=0;d.call(this,t,function(t,e){t.span>c&&(c=t.span),t.stop(),t.animate(e)},function(t){\"wait\"in t&&(c=u(t.wait,0))}),h.call(this),c>0&&(this.timer=new N({duration:c,context:this}),this.active=!0,e&&(this.timer.complete=s));var p=this,v=!1,m={};B(function(){d.call(p,t,function(t){t.active&&(v=!0,m[t.name]=t.nextStyle)}),v&&p.$el.css(m)})}}}function s(){if(this.timer&&this.timer.destroy(),this.active=!1,this.queue.length){var t=this.queue.shift();o.call(this,t.options,!0,t.args)}}function a(t){var e;this.timer&&this.timer.destroy(),this.queue=[],this.active=!1,\"string\"==typeof t?(e={})[t]=1:e=\"object\"==(void 0===t?\"undefined\":n(t))&&null!=t?t:this.props,d.call(this,e,p),h.call(this)}function l(){a.call(this),this.el.style.display=\"none\"}function f(){this.el.offsetHeight}function h(){var t,e,n=[];for(t in this.upstream&&n.push(this.upstream),this.props)(e=this.props[t]).active&&n.push(e.string);n=n.join(\",\"),this.style!==n&&(this.style=n,this.el.style[$.transition.dom]=n)}function d(t,e,n){var o,s,a,u,c=e!==p,l={};for(o in t)a=t[o],o in Q?(l.transform||(l.transform={}),l.transform[o]=a):(w.test(o)&&(o=i(o)),o in W?l[o]=a:(u||(u={}),u[o]=a));for(o in l){if(a=l[o],!(s=this.props[o])){if(!c)continue;s=r.call(this,o)}e.call(this,s,a)}n&&u&&n.call(this,u)}function p(t){t.stop()}function m(t,e){t.set(e)}function g(t){this.$el.css(t)}function b(t,n){e[t]=function(){return this.children?function(t,e){var n,i=this.children.length;for(n=0;i>n;n++)t.apply(this.children[n],e);return this}.call(this,n,arguments):(this.el&&n.apply(this,arguments),this)}}e.init=function(e){if(this.$el=t(e),this.el=this.$el[0],this.props={},this.queue=[],this.style=\"\",this.active=!1,X.keepInherited&&!X.fallback){var n=G(this.el,\"transition\");n&&!z.test(n)&&(this.upstream=n)}$.backface&&X.hideBackface&&Y(this.el,$.backface.css,\"hidden\")},b(\"add\",r),b(\"start\",o),b(\"wait\",function(t){t=u(t,0),this.active?this.queue.push({options:t}):(this.timer=new N({duration:t,context:this,complete:s}),this.active=!0)}),b(\"then\",function(t){return this.active?(this.queue.push({options:t,args:arguments}),void(this.timer.complete=s)):c(\"No active transition timer. Use start() or wait() before then().\")}),b(\"next\",s),b(\"stop\",a),b(\"set\",function(t){a.call(this,t),d.call(this,t,m,g)}),b(\"show\",function(t){\"string\"!=typeof t&&(t=\"block\"),this.el.style.display=t}),b(\"hide\",l),b(\"redraw\",f),b(\"destroy\",function(){a.call(this),t.removeData(this.el,v),this.$el=this.el=null})}),L=l(F,function(e){function n(e,n){var i=t.data(e,v)||t.data(e,v,new F.Bare);return i.el||i.init(e),n?i.start(n):i}e.init=function(e,i){var r=t(e);if(!r.length)return this;if(1===r.length)return n(r[0],i);var o=[];return r.each(function(t,e){o.push(n(e,i))}),this.children=o,this}}),D=l(function(t){function e(){var t=this.get();this.update(\"auto\");var e=this.get();return this.update(t),e}function i(t){var e=/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/.exec(t);return(e?o(e[1],e[2],e[3]):t).replace(/#(\\w)(\\w)(\\w)$/,\"#$1$1$2$2$3$3\")}var r=500,s=\"ease\",a=0;t.init=function(t,e,n,i){this.$el=t,this.el=t[0];var o=e[0];n[2]&&(o=n[2]),Z[o]&&(o=Z[o]),this.name=o,this.type=n[1],this.duration=u(e[1],this.duration,r),this.ease=function(t,e,n){return void 0!==e&&(n=e),t in f?t:n}(e[2],this.ease,s),this.delay=u(e[3],this.delay,a),this.span=this.duration+this.delay,this.active=!1,this.nextStyle=null,this.auto=T.test(this.name),this.unit=i.unit||this.unit||X.defaultUnit,this.angle=i.angle||this.angle||X.defaultAngle,X.fallback||i.fallback?this.animate=this.fallback:(this.animate=this.transition,this.string=this.name+E+this.duration+\"ms\"+(\"ease\"!=this.ease?E+f[this.ease][0]:\"\")+(this.delay?E+this.delay+\"ms\":\"\"))},t.set=function(t){t=this.convert(t,this.type),this.update(t),this.redraw()},t.transition=function(t){this.active=!0,t=this.convert(t,this.type),this.auto&&(\"auto\"==this.el.style[this.name]&&(this.update(this.get()),this.redraw()),\"auto\"==t&&(t=e.call(this))),this.nextStyle=t},t.fallback=function(t){var n=this.el.style[this.name]||this.convert(this.get(),this.type);t=this.convert(t,this.type),this.auto&&(\"auto\"==n&&(n=this.convert(this.get(),this.type)),\"auto\"==t&&(t=e.call(this))),this.tween=new C({from:n,to:t,duration:this.duration,delay:this.delay,ease:this.ease,update:this.update,context:this})},t.get=function(){return G(this.el,this.name)},t.update=function(t){Y(this.el,this.name,t)},t.stop=function(){(this.active||this.nextStyle)&&(this.active=!1,this.nextStyle=null,Y(this.el,this.name,this.get()));var t=this.tween;t&&t.context&&t.destroy()},t.convert=function(t,e){if(\"auto\"==t&&this.auto)return t;var r,o=\"number\"==typeof t,s=\"string\"==typeof t;switch(e){case g:if(o)return t;if(s&&\"\"===t.replace(m,\"\"))return+t;r=\"number(unitless)\";break;case b:if(s){if(\"\"===t&&this.original)return this.original;if(e.test(t))return\"#\"==t.charAt(0)&&7==t.length?t:i(t)}r=\"hex or rgb string\";break;case y:if(o)return t+this.unit;if(s&&e.test(t))return t;r=\"number(px) or string(unit)\";break;case x:if(o)return t+this.unit;if(s&&e.test(t))return t;r=\"number(px) or string(unit or %)\";break;case _:if(o)return t+this.angle;if(s&&e.test(t))return t;r=\"number(deg) or string(angle)\";break;case k:if(o)return t;if(s&&x.test(t))return t;r=\"number(unitless) or string(unit or %)\"}return function(t,e){c(\"Type warning: Expected: [\"+t+\"] Got: [\"+(void 0===e?\"undefined\":n(e))+\"] \"+e)}(r,t),t},t.redraw=function(){this.el.offsetHeight}}),I=l(D,function(t,e){t.init=function(){e.init.apply(this,arguments),this.original||(this.original=this.convert(this.get(),b))}}),P=l(D,function(t,e){t.init=function(){e.init.apply(this,arguments),this.animate=this.fallback},t.get=function(){return this.$el[this.name]()},t.update=function(t){this.$el[this.name](t)}}),H=l(D,function(t,e){function n(t,e){var n,i,r,o,s;for(n in t)r=(o=Q[n])[0],i=o[1]||n,s=this.convert(t[n],r),e.call(this,i,s,r)}t.init=function(){e.init.apply(this,arguments),this.current||(this.current={},Q.perspective&&X.perspective&&(this.current.perspective=X.perspective,Y(this.el,this.name,this.style(this.current)),this.redraw()))},t.set=function(t){n.call(this,t,function(t,e){this.current[t]=e}),Y(this.el,this.name,this.style(this.current)),this.redraw()},t.transition=function(t){var e=this.values(t);this.tween=new U({current:this.current,values:e,duration:this.duration,delay:this.delay,ease:this.ease});var n,i={};for(n in this.current)i[n]=n in e?e[n]:this.current[n];this.active=!0,this.nextStyle=this.style(i)},t.fallback=function(t){var e=this.values(t);this.tween=new U({current:this.current,values:e,duration:this.duration,delay:this.delay,ease:this.ease,update:this.update,context:this})},t.update=function(){Y(this.el,this.name,this.style(this.current))},t.style=function(t){var e,n=\"\";for(e in t)n+=e+\"(\"+t[e]+\") \";return n},t.values=function(t){var e,i={};return n.call(this,t,function(t,n,r){i[t]=n,void 0===this.current[t]&&(e=0,~t.indexOf(\"scale\")&&(e=1),this.current[t]=this.convert(e,r))}),i}}),C=l(function(e){function n(){var t,e,i,r=u.length;if(r)for(B(n),e=R(),t=r;t--;)(i=u[t])&&i.render(e)}var i={ease:f.ease[1],from:0,to:1};e.init=function(t){this.duration=t.duration||0,this.delay=t.delay||0;var e=t.ease||i.ease;f[e]&&(e=f[e][1]),\"function\"!=typeof e&&(e=i.ease),this.ease=e,this.update=t.update||s,this.complete=t.complete||s,this.context=t.context||this,this.name=t.name;var n=t.from,r=t.to;void 0===n&&(n=i.from),void 0===r&&(r=i.to),this.unit=t.unit||\"\",\"number\"==typeof n&&\"number\"==typeof r?(this.begin=n,this.change=r-n):this.format(r,n),this.value=this.begin+this.unit,this.start=R(),!1!==t.autoplay&&this.play()},e.play=function(){var t;this.active||(this.start||(this.start=R()),this.active=!0,t=this,1===u.push(t)&&B(n))},e.stop=function(){var e,n,i;this.active&&(this.active=!1,e=this,(i=t.inArray(e,u))>=0&&(n=u.slice(i+1),u.length=i,n.length&&(u=u.concat(n))))},e.render=function(t){var e,n=t-this.start;if(this.delay){if(n<=this.delay)return;n-=this.delay}if(n<this.duration){var i=this.ease(n,0,1,this.duration);return e=this.startRGB?function(t,e,n){return o(t[0]+n*(e[0]-t[0]),t[1]+n*(e[1]-t[1]),t[2]+n*(e[2]-t[2]))}(this.startRGB,this.endRGB,i):function(t){return Math.round(t*c)/c}(this.begin+i*this.change),this.value=e+this.unit,void this.update.call(this.context,this.value)}e=this.endHex||this.begin+this.change,this.value=e+this.unit,this.update.call(this.context,this.value),this.complete.call(this.context),this.destroy()},e.format=function(t,e){if(e+=\"\",\"#\"==(t+=\"\").charAt(0))return this.startRGB=r(e),this.endRGB=r(t),this.endHex=t,this.begin=0,void(this.change=1);if(!this.unit){var n=e.replace(m,\"\");n!==t.replace(m,\"\")&&a(\"tween\",e,t),this.unit=n}e=parseFloat(e),t=parseFloat(t),this.begin=this.value=e,this.change=t-e},e.destroy=function(){this.stop(),this.context=null,this.ease=this.update=this.complete=s};var u=[],c=1e3}),N=l(C,function(t){t.init=function(t){this.duration=t.duration||0,this.complete=t.complete||s,this.context=t.context,this.play()},t.render=function(t){t-this.start<this.duration||(this.complete.call(this.context),this.destroy())}}),U=l(C,function(t,e){t.init=function(t){var e,n;for(e in this.context=t.context,this.update=t.update,this.tweens=[],this.current=t.current,t.values)n=t.values[e],this.current[e]!==n&&this.tweens.push(new C({name:e,from:this.current[e],to:n,duration:t.duration,delay:t.delay,ease:t.ease,autoplay:!1}));this.play()},t.render=function(t){var e,n,i=!1;for(e=this.tweens.length;e--;)(n=this.tweens[e]).context&&(n.render(t),this.current[n.name]=n.value,i=!0);return i?void(this.update&&this.update.call(this.context)):this.destroy()},t.destroy=function(){if(e.destroy.call(this),this.tweens){var t;for(t=this.tweens.length;t--;)this.tweens[t].destroy();this.tweens=null,this.current=null}}}),X=e.config={debug:!1,defaultUnit:\"px\",defaultAngle:\"deg\",keepInherited:!1,hideBackface:!1,perspective:\"\",fallback:!$.transition,agentTests:[]};e.fallback=function(t){if(!$.transition)return X.fallback=!0;X.agentTests.push(\"(\"+t+\")\");var e=new RegExp(X.agentTests.join(\"|\"),\"i\");X.fallback=e.test(navigator.userAgent)},e.fallback(\"6.0.[2-5] Safari\"),e.tween=function(t){return new C(t)},e.delay=function(t,e,n){return new N({complete:e,duration:t,context:n})},t.fn.tram=function(t){return e.call(null,this,t)};var Y=t.style,G=t.css,Z={transform:$.transform&&$.transform.css},W={color:[I,b],background:[I,b,\"background-color\"],\"outline-color\":[I,b],\"border-color\":[I,b],\"border-top-color\":[I,b],\"border-right-color\":[I,b],\"border-bottom-color\":[I,b],\"border-left-color\":[I,b],\"border-width\":[D,y],\"border-top-width\":[D,y],\"border-right-width\":[D,y],\"border-bottom-width\":[D,y],\"border-left-width\":[D,y],\"border-spacing\":[D,y],\"letter-spacing\":[D,y],margin:[D,y],\"margin-top\":[D,y],\"margin-right\":[D,y],\"margin-bottom\":[D,y],\"margin-left\":[D,y],padding:[D,y],\"padding-top\":[D,y],\"padding-right\":[D,y],\"padding-bottom\":[D,y],\"padding-left\":[D,y],\"outline-width\":[D,y],opacity:[D,g],top:[D,x],right:[D,x],bottom:[D,x],left:[D,x],\"font-size\":[D,x],\"text-indent\":[D,x],\"word-spacing\":[D,x],width:[D,x],\"min-width\":[D,x],\"max-width\":[D,x],height:[D,x],\"min-height\":[D,x],\"max-height\":[D,x],\"line-height\":[D,k],\"scroll-top\":[P,g,\"scrollTop\"],\"scroll-left\":[P,g,\"scrollLeft\"]},Q={};$.transform&&(W.transform=[H],Q={x:[x,\"translateX\"],y:[x,\"translateY\"],rotate:[_],rotateX:[_],rotateY:[_],scale:[g],scaleX:[g],scaleY:[g],skew:[_],skewX:[_],skewY:[_]}),$.transform&&$.backface&&(Q.z=[x,\"translateZ\"],Q.rotateZ=[_],Q.scaleZ=[g],Q.perspective=[y]);var J=/ms/,V=/s|\\./;return t.tram=e}(window.jQuery)},function(t,e,n){n(3),n(5),n(7),n(8),t.exports=n(9)},function(t,e,n){var i=n(0);i.define(\"brand\",t.exports=function(t){var e,n={},r=document,o=t(\"html\"),s=t(\"body\"),a=\".w-webflow-badge\",u=window.location,c=/PhantomJS/i.test(navigator.userAgent),l=\"fullscreenchange webkitfullscreenchange mozfullscreenchange msfullscreenchange\";function f(){var n=r.fullScreen||r.mozFullScreen||r.webkitIsFullScreen||r.msFullscreenElement||Boolean(r.webkitFullscreenElement);t(e).attr(\"style\",n?\"display: none !important;\":\"\")}function h(){var t=s.children(a),n=t.length&&t.get(0)===e,r=i.env(\"editor\");n?r&&t.remove():(t.length&&t.remove(),r||s.append(e))}return n.ready=function(){var n,i,s,a=o.attr(\"data-wf-status\"),d=o.attr(\"data-wf-domain\")||\"\";/\\.webflow\\.io$/i.test(d)&&u.hostname!==d&&(a=!0),a&&!c&&(e=e||(n=t('<a class=\"w-webflow-badge\"></a>').attr(\"href\",\"https://webflow.com?utm_campaign=brandjs\"),i=t(\"<img>\").attr(\"src\",\"https://d1otoma47x30pg.cloudfront.net/img/webflow-badge-icon.60efbf6ec9.svg\").css({marginRight:\"8px\",width:\"16px\"}),s=t(\"<img>\").attr(\"src\",\"https://d1otoma47x30pg.cloudfront.net/img/webflow-badge-text.6faa6a38cd.svg\"),n.append(i,s),n[0]),h(),setTimeout(h,500),t(r).off(l,f).on(l,f))},n})},function(t,e,n){var i=window.$,r=n(1)&&i.tram;\n/*!\n * Webflow._ (aka) Underscore.js 1.6.0 (custom build)\n * _.each\n * _.map\n * _.find\n * _.filter\n * _.any\n * _.contains\n * _.delay\n * _.defer\n * _.throttle (webflow)\n * _.debounce\n * _.keys\n * _.has\n * _.now\n *\n * http://underscorejs.org\n * (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Underscore may be freely distributed under the MIT license.\n * @license MIT\n */\nt.exports=function(){var t={VERSION:\"1.6.0-Webflow\"},e={},n=Array.prototype,i=Object.prototype,o=Function.prototype,s=(n.push,n.slice),a=(n.concat,i.toString,i.hasOwnProperty),u=n.forEach,c=n.map,l=(n.reduce,n.reduceRight,n.filter),f=(n.every,n.some),h=n.indexOf,d=(n.lastIndexOf,Array.isArray,Object.keys),p=(o.bind,t.each=t.forEach=function(n,i,r){if(null==n)return n;if(u&&n.forEach===u)n.forEach(i,r);else if(n.length===+n.length){for(var o=0,s=n.length;o<s;o++)if(i.call(r,n[o],o,n)===e)return}else{var a=t.keys(n);for(o=0,s=a.length;o<s;o++)if(i.call(r,n[a[o]],a[o],n)===e)return}return n});t.map=t.collect=function(t,e,n){var i=[];return null==t?i:c&&t.map===c?t.map(e,n):(p(t,function(t,r,o){i.push(e.call(n,t,r,o))}),i)},t.find=t.detect=function(t,e,n){var i;return v(t,function(t,r,o){if(e.call(n,t,r,o))return i=t,!0}),i},t.filter=t.select=function(t,e,n){var i=[];return null==t?i:l&&t.filter===l?t.filter(e,n):(p(t,function(t,r,o){e.call(n,t,r,o)&&i.push(t)}),i)};var v=t.some=t.any=function(n,i,r){i||(i=t.identity);var o=!1;return null==n?o:f&&n.some===f?n.some(i,r):(p(n,function(t,n,s){if(o||(o=i.call(r,t,n,s)))return e}),!!o)};t.contains=t.include=function(t,e){return null!=t&&(h&&t.indexOf===h?-1!=t.indexOf(e):v(t,function(t){return t===e}))},t.delay=function(t,e){var n=s.call(arguments,2);return setTimeout(function(){return t.apply(null,n)},e)},t.defer=function(e){return t.delay.apply(t,[e,1].concat(s.call(arguments,1)))},t.throttle=function(t){var e,n,i;return function(){e||(e=!0,n=arguments,i=this,r.frame(function(){e=!1,t.apply(i,n)}))}},t.debounce=function(e,n,i){var r,o,s,a,u,c=function c(){var l=t.now()-a;l<n?r=setTimeout(c,n-l):(r=null,i||(u=e.apply(s,o),s=o=null))};return function(){s=this,o=arguments,a=t.now();var l=i&&!r;return r||(r=setTimeout(c,n)),l&&(u=e.apply(s,o),s=o=null),u}},t.defaults=function(e){if(!t.isObject(e))return e;for(var n=1,i=arguments.length;n<i;n++){var r=arguments[n];for(var o in r)void 0===e[o]&&(e[o]=r[o])}return e},t.keys=function(e){if(!t.isObject(e))return[];if(d)return d(e);var n=[];for(var i in e)t.has(e,i)&&n.push(i);return n},t.has=function(t,e){return a.call(t,e)},t.isObject=function(t){return t===Object(t)},t.now=Date.now||function(){return(new Date).getTime()},t.templateSettings={evaluate:/<%([\\s\\S]+?)%>/g,interpolate:/<%=([\\s\\S]+?)%>/g,escape:/<%-([\\s\\S]+?)%>/g};var m=/(.)^/,w={\"'\":\"'\",\"\\\\\":\"\\\\\",\"\\r\":\"r\",\"\\n\":\"n\",\"\\u2028\":\"u2028\",\"\\u2029\":\"u2029\"},g=/\\\\|'|\\r|\\n|\\u2028|\\u2029/g,b=function(t){return\"\\\\\"+w[t]};return t.template=function(e,n,i){!n&&i&&(n=i),n=t.defaults({},n,t.templateSettings);var r=RegExp([(n.escape||m).source,(n.interpolate||m).source,(n.evaluate||m).source].join(\"|\")+\"|$\",\"g\"),o=0,s=\"__p+='\";e.replace(r,function(t,n,i,r,a){return s+=e.slice(o,a).replace(g,b),o=a+t.length,n?s+=\"'+\\n((__t=(\"+n+\"))==null?'':_.escape(__t))+\\n'\":i?s+=\"'+\\n((__t=(\"+i+\"))==null?'':__t)+\\n'\":r&&(s+=\"';\\n\"+r+\"\\n__p+='\"),t}),s+=\"';\\n\",n.variable||(s=\"with(obj||{}){\\n\"+s+\"}\\n\"),s=\"var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\\n\"+s+\"return __p;\\n\";try{var a=new Function(n.variable||\"obj\",\"_\",s)}catch(t){throw t.source=s,t}var u=function(e){return a.call(this,e,t)},c=n.variable||\"obj\";return u.source=\"function(\"+c+\"){\\n\"+s+\"}\",u},t}()},function(t,e,n){var i=n(0),r=n(6);i.define(\"ix\",t.exports=function(t,e){var n,o,s={},a=t(window),u=\".w-ix\",c=t.tram,l=i.env,f=l(),h=l.chrome&&l.chrome<35,d=\"none 0s ease 0s\",p=t(),v={},m=[],w=[],g=[],b=1,y={tabs:\".w-tab-link, .w-tab-pane\",dropdown:\".w-dropdown\",slider:\".w-slide\",navbar:\".w-nav\"};function x(t){t&&(v={},e.each(t,function(t){v[t.slug]=t.value}),_())}function _(){!function(){var e=t(\"[data-ix]\");if(!e.length)return;e.each(T),e.each(k),m.length&&(i.scroll.on(E),setTimeout(E,1));w.length&&i.load(q);g.length&&setTimeout(O,b)}(),r.init(),i.redraw.up()}function k(n,o){var a=t(o),c=a.attr(\"data-ix\"),l=v[c];if(l){var h=l.triggers;h&&(s.style(a,l.style),e.each(h,function(t){var e={},n=t.type,o=t.stepsB&&t.stepsB.length;function s(){A(t,a,{group:\"A\"})}function c(){A(t,a,{group:\"B\"})}if(\"load\"!==n){if(\"click\"===n)return a.on(\"click\"+u,function(n){i.validClick(n.currentTarget)&&(\"#\"===a.attr(\"href\")&&n.preventDefault(),A(t,a,{group:e.clicked?\"B\":\"A\"}),o&&(e.clicked=!e.clicked))}),void(p=p.add(a));if(\"hover\"===n)return a.on(\"mouseenter\"+u,s),a.on(\"mouseleave\"+u,c),void(p=p.add(a));if(\"scroll\"!==n){var l=y[n];if(l){var h=a.closest(l);return h.on(r.types.INTRO,s).on(r.types.OUTRO,c),void(p=p.add(h))}}else m.push({el:a,trigger:t,state:{active:!1},offsetTop:z(t.offsetTop),offsetBot:z(t.offsetBot)})}else t.preload&&!f?w.push(s):g.push(s)}))}}function z(t){if(!t)return 0;t=String(t);var e=parseInt(t,10);return e!=e?0:(t.indexOf(\"%\")>0&&(e/=100)>=1&&(e=.999),e)}function T(e,n){t(n).off(u)}function E(){for(var t=a.scrollTop(),e=a.height(),n=m.length,i=0;i<n;i++){var r=m[i],o=r.el,s=r.trigger,u=s.stepsB&&s.stepsB.length,c=r.state,l=o.offset().top,f=o.outerHeight(),h=r.offsetTop,d=r.offsetBot;h<1&&h>0&&(h*=e),d<1&&d>0&&(d*=e);var p=l+f-h>=t&&l+d<=t+e;p!==c.active&&((!1!==p||u)&&(c.active=p,A(s,o,{group:p?\"A\":\"B\"})))}}function q(){for(var t=w.length,e=0;e<t;e++)w[e]()}function O(){for(var t=g.length,e=0;e<t;e++)g[e]()}function A(e,i,r,o){var s=(r=r||{}).done,a=e.preserve3d;if(!n||r.force){var u=r.group||\"A\",l=e[\"loop\"+u],d=e[\"steps\"+u];if(d&&d.length){if(d.length<2&&(l=!1),!o){var p=e.selector;p&&(i=e.descend?i.find(p):e.siblings?i.siblings(p):t(p),f&&i.attr(\"data-ix-affect\",1)),h&&i.addClass(\"w-ix-emptyfix\"),a&&i.css(\"transform-style\",\"preserve-3d\")}for(var v=c(i),m={omit3d:!a},w=0;w<d.length;w++)S(v,d[w],m);m.start?v.then(g):g()}}function g(){if(l)return A(e,i,r,!0);\"auto\"===m.width&&v.set({width:\"auto\"}),\"auto\"===m.height&&v.set({height:\"auto\"}),s&&s()}}function S(t,e,n){var r=\"add\",o=\"start\";n.start&&(r=o=\"then\");var s=e.transition;if(s){s=s.split(\",\");for(var a=0;a<s.length;a++){var u=s[a];t[r](u)}}var c=$(e,n)||{};if(null!=c.width&&(n.width=c.width),null!=c.height&&(n.height=c.height),null==s){n.start?t.then(function(){var e=this.queue;this.set(c),c.display&&(t.redraw(),i.redraw.up()),this.queue=e,this.next()}):(t.set(c),c.display&&(t.redraw(),i.redraw.up()));var l=c.wait;null!=l&&(t.wait(l),n.start=!0)}else{if(c.display){var f=c.display;delete c.display,n.start?t.then(function(){var t=this.queue;this.set({display:f}).redraw(),i.redraw.up(),this.queue=t,this.next()}):(t.set({display:f}).redraw(),i.redraw.up())}t[o](c),n.start=!0}}function $(t,e){var n=e&&e.omit3d,i={},r=!1;for(var o in t)\"transition\"!==o&&\"keysort\"!==o&&(!n||\"z\"!==o&&\"rotateX\"!==o&&\"rotateY\"!==o&&\"scaleZ\"!==o)&&(i[o]=t[o],r=!0);return r?i:null}return s.init=function(t){setTimeout(function(){x(t)},1)},s.preview=function(){n=!1,b=100,setTimeout(function(){x(window.__wf_ix)},1)},s.design=function(){n=!0,s.destroy()},s.destroy=function(){o=!0,p.each(T),i.scroll.off(E),r.async(),m=[],w=[],g=[]},s.ready=function(){if(f)return l(\"design\")?s.design():s.preview();v&&o&&(o=!1,_())},s.run=A,s.style=f?function(e,n){var i=c(e);if(t.isEmptyObject(n))return;e.css(\"transition\",\"\");var r=e.css(\"transition\");r===d&&(r=i.upstream=null);i.upstream=d,i.set($(n)),i.upstream=r}:function(t,e){c(t).set($(e))},s})},function(t,e,n){\"use strict\";var i=window.jQuery,r={},o=[],s={reset:function(t,e){e.__wf_intro=null},intro:function(t,e){e.__wf_intro||(e.__wf_intro=!0,i(e).triggerHandler(r.types.INTRO))},outro:function(t,e){e.__wf_intro&&(e.__wf_intro=null,i(e).triggerHandler(r.types.OUTRO))}};r.triggers={},r.types={INTRO:\"w-ix-intro.w-ix\",OUTRO:\"w-ix-outro.w-ix\"},r.init=function(){for(var t=o.length,e=0;e<t;e++){var n=o[e];n[0](0,n[1])}o=[],i.extend(r.triggers,s)},r.async=function(){for(var t in s){var e=s[t];s.hasOwnProperty(t)&&(r.triggers[t]=function(t,n){o.push([e,n])})}},r.async(),t.exports=r},function(t,e,n){var i=n(0);i.define(\"links\",t.exports=function(t,e){var n,r,o,s={},a=t(window),u=i.env(),c=window.location,l=document.createElement(\"a\"),f=\"w--current\",h=/^#[\\w:.-]+$/,d=/index\\.(html|php)$/,p=/\\/$/;function v(e){var i=n&&e.getAttribute(\"href-disabled\")||e.getAttribute(\"href\");if(l.href=i,!(i.indexOf(\":\")>=0)){var s=t(e);if(0===i.indexOf(\"#\")&&h.test(i)){var a=t(i);a.length&&r.push({link:s,sec:a,active:!1})}else if(\"#\"!==i&&\"\"!==i){var u=l.href===c.href||i===o||d.test(i)&&p.test(o);w(s,f,u)}}}function m(){var t=a.scrollTop(),n=a.height();e.each(r,function(e){var i=e.link,r=e.sec,o=r.offset().top,s=r.outerHeight(),a=.5*n,u=r.is(\":visible\")&&o+s-a>=t&&o+a<=t+n;e.active!==u&&(e.active=u,w(i,f,u))})}function w(t,e,n){var i=t.hasClass(e);n&&i||(n||i)&&(n?t.addClass(e):t.removeClass(e))}return s.ready=s.design=s.preview=function(){n=u&&i.env(\"design\"),o=i.env(\"slug\")||c.pathname||\"\",i.scroll.off(m),r=[];for(var t=document.links,e=0;e<t.length;++e)v(t[e]);r.length&&(i.scroll.on(m),m())},s})},function(t,e,n){var i=n(0);i.define(\"scroll\",t.exports=function(t){var e=t(document),n=window,r=n.location,o=function(){try{return Boolean(n.frameElement)}catch(t){return!0}}()?null:n.history,s=/^[a-zA-Z0-9][\\w:.-]*$/;function a(e,a){if(s.test(e)){var u=t(\"#\"+e);if(u.length){if(a&&(a.preventDefault(),a.stopPropagation()),r.hash!==e&&o&&o.pushState&&(!i.env.chrome||\"file:\"!==r.protocol))(o.state&&o.state.hash)!==e&&o.pushState({hash:e},\"\",\"#\"+e);var c=i.env(\"editor\")?\".w-editor-body\":\"body\",l=t(\"header, \"+c+\" > .header, \"+c+\" > .w-nav:not([data-no-scroll])\"),f=\"fixed\"===l.css(\"position\")?l.outerHeight():0;n.setTimeout(function(){!function(e,i){var r=t(n).scrollTop(),o=e.offset().top-i;if(\"mid\"===e.data(\"scroll\")){var s=t(n).height()-i,a=e.outerHeight();a<s&&(o-=Math.round((s-a)/2))}var u=1;t(\"body\").add(e).each(function(){var e=parseFloat(t(this).attr(\"data-scroll-time\"),10);!isNaN(e)&&(0===e||e>0)&&(u=e)}),Date.now||(Date.now=function(){return(new Date).getTime()});var c=Date.now(),l=n.requestAnimationFrame||n.mozRequestAnimationFrame||n.webkitRequestAnimationFrame||function(t){n.setTimeout(t,15)},f=(472.143*Math.log(Math.abs(r-o)+125)-2e3)*u;!function t(){var e=Date.now()-c;n.scroll(0,function(t,e,n,i){if(n>i)return e;return t+(e-t)*(r=n/i,r<.5?4*r*r*r:(r-1)*(2*r-2)*(2*r-2)+1);var r}(r,o,e,f)),e<=f&&l(t)}()}(u,f)},a?0:300)}}}return{ready:function(){r.hash&&a(r.hash.substring(1));var n=r.href.split(\"#\")[0];e.on(\"click\",\"a\",function(e){if(!(i.env(\"design\")||window.$.mobile&&t(e.currentTarget).hasClass(\"ui-link\")))if(\"#\"!==this.getAttribute(\"href\")){var r=this.href.split(\"#\"),o=r[0]===n?r[1]:null;o&&a(o,e)}else e.preventDefault()})}}})},function(t,e,n){n(0).define(\"touch\",t.exports=function(t){var e={},n=!document.addEventListener,i=window.getSelection;function r(e,n,i){var r=t.Event(e,{originalEvent:n});t(n.target).trigger(r,i)}return n&&(t.event.special.tap={bindType:\"click\",delegateType:\"click\"}),e.init=function(e){return n?null:(e=\"string\"==typeof e?t(e).get(0):e)?new function(t){var e,n,o,s=!1,a=!1,u=!1,c=Math.min(Math.round(.04*window.innerWidth),40);function l(t){var i=t.touches;i&&i.length>1||(s=!0,a=!1,i?(u=!0,e=i[0].clientX,n=i[0].clientY):(e=t.clientX,n=t.clientY),o=e)}function f(t){if(s){if(u&&\"mousemove\"===t.type)return t.preventDefault(),void t.stopPropagation();var l=t.touches,f=l?l[0].clientX:t.clientX,h=l?l[0].clientY:t.clientY,p=f-o;o=f,Math.abs(p)>c&&i&&\"\"===String(i())&&(r(\"swipe\",t,{direction:p>0?\"right\":\"left\"}),d()),(Math.abs(f-e)>10||Math.abs(h-n)>10)&&(a=!0)}}function h(t){if(s){if(s=!1,u&&\"mouseup\"===t.type)return t.preventDefault(),t.stopPropagation(),void(u=!1);a||r(\"tap\",t)}}function d(){s=!1}t.addEventListener(\"touchstart\",l,!1),t.addEventListener(\"touchmove\",f,!1),t.addEventListener(\"touchend\",h,!1),t.addEventListener(\"touchcancel\",d,!1),t.addEventListener(\"mousedown\",l,!1),t.addEventListener(\"mousemove\",f,!1),t.addEventListener(\"mouseup\",h,!1),t.addEventListener(\"mouseout\",d,!1),this.destroy=function(){t.removeEventListener(\"touchstart\",l,!1),t.removeEventListener(\"touchmove\",f,!1),t.removeEventListener(\"touchend\",h,!1),t.removeEventListener(\"touchcancel\",d,!1),t.removeEventListener(\"mousedown\",l,!1),t.removeEventListener(\"mousemove\",f,!1),t.removeEventListener(\"mouseup\",h,!1),t.removeEventListener(\"mouseout\",d,!1),t=null}}(e):null},e.instance=e.init(document),e})}]);/**\n * ----------------------------------------------------------------------\n * Webflow: Interactions: Init\n */\nWebflow.require('ix').init([\n  {\"slug\":\"new-interaction\",\"name\":\"New Interaction\",\"value\":{\"style\":{},\"triggers\":[{\"type\":\"click\",\"stepsA\":[{\"display\":\"flex\"}],\"stepsB\":[]}]}},\n  {\"slug\":\"display-none\",\"name\":\"Display None\",\"value\":{\"style\":{\"display\":\"none\"},\"triggers\":[]}}\n]);\n"
  }
]